Decompiled source of CrawlCustomBosses v1.0.0

plugins/CrawlCustomBosses/CrawlBossKit.dll

Decompiled 4 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("CrawlBossKit")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("CrawlBossKit")]
[assembly: AssemblyTitle("CrawlBossKit")]
[assembly: AssemblyVersion("1.0.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 BossKit
{
	public static class KitArt
	{
		public sealed class Sheet
		{
			private readonly string m_name;

			private readonly List<Texture2D> m_frames = new List<Texture2D>();

			private readonly Dictionary<string, int[]> m_strips = new Dictionary<string, int[]>();

			public exAtlas Atlas { get; private set; }

			public string Name => m_name;

			public Sheet(string name)
			{
				m_name = name;
			}

			private void CheckOpen(string key)
			{
				if ((Object)(object)Atlas != (Object)null)
				{
					throw new InvalidOperationException("sheet " + m_name + " is already built; cannot add " + key);
				}
				if (m_strips.ContainsKey(key))
				{
					throw new ArgumentException("sheet " + m_name + " already has a strip " + key);
				}
			}

			public void AddStrip(string key, Texture2D strip, int frames)
			{
				CheckOpen(key);
				List<Texture2D> collection = Slice(strip, frames);
				int count = m_frames.Count;
				m_frames.AddRange(collection);
				m_strips[key] = Enumerable.Range(count, frames).ToArray();
			}

			public void AddStrip(string key, BossAssets assets, string logicalName, int frames)
			{
				AddStrip(key, assets.Png(logicalName), frames);
			}

			public void AddGrid(string key, BossAssets assets, string logicalName, int cols, int rows)
			{
				//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e9: Expected O, but got Unknown
				CheckOpen(key);
				Texture2D val = assets.Png(logicalName);
				if (cols < 1 || rows < 1 || ((Texture)val).width % cols != 0 || ((Texture)val).height % rows != 0)
				{
					throw new FormatException(logicalName + " (" + ((Texture)val).width + "x" + ((Texture)val).height + ") does not divide into " + cols + "x" + rows + " tiles");
				}
				int num = ((Texture)val).width / cols;
				int num2 = ((Texture)val).height / rows;
				int count = m_frames.Count;
				for (int i = 0; i < rows; i++)
				{
					for (int j = 0; j < cols; j++)
					{
						Texture2D val2 = new Texture2D(num, num2, (TextureFormat)5, false)
						{
							filterMode = (FilterMode)0,
							wrapMode = (TextureWrapMode)1
						};
						val2.SetPixels(val.GetPixels(j * num, ((Texture)val).height - (i + 1) * num2, num, num2));
						val2.Apply();
						m_frames.Add(val2);
					}
				}
				m_strips[key] = Enumerable.Range(count, cols * rows).ToArray();
			}

			public int[] Frames(string key)
			{
				if (!m_strips.TryGetValue(key, out var value))
				{
					throw new KeyNotFoundException("no strip " + key + " in sheet " + m_name);
				}
				return value;
			}

			public bool Has(string key)
			{
				return m_strips.ContainsKey(key);
			}

			public void Build(Material baseMaterial)
			{
				//IL_007e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0084: Expected O, but got Unknown
				//IL_019b: Unknown result type (might be due to invalid IL or missing references)
				//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
				//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
				//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
				//IL_01c6: Expected O, but got Unknown
				//IL_0214: Unknown result type (might be due to invalid IL or missing references)
				//IL_0219: Unknown result type (might be due to invalid IL or missing references)
				//IL_0236: Unknown result type (might be due to invalid IL or missing references)
				//IL_024e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0266: Unknown result type (might be due to invalid IL or missing references)
				//IL_0297: 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_02a1: Unknown result type (might be due to invalid IL or missing references)
				//IL_02a5: Unknown result type (might be due to invalid IL or missing references)
				//IL_02aa: Unknown result type (might be due to invalid IL or missing references)
				//IL_02af: Unknown result type (might be due to invalid IL or missing references)
				//IL_02b7: Expected O, but got Unknown
				if ((Object)(object)Atlas != (Object)null)
				{
					throw new InvalidOperationException("sheet " + m_name + " is already built");
				}
				if ((Object)(object)baseMaterial == (Object)null)
				{
					throw new ArgumentNullException("baseMaterial", "sheet " + m_name + " needs a base material");
				}
				if (m_frames.Count == 0)
				{
					throw new InvalidOperationException("sheet " + m_name + " has no frames");
				}
				Texture2D val = new Texture2D(1, 1, (TextureFormat)5, false);
				Rect[] array = val.PackTextures(m_frames.ToArray(), 2, 4096, false);
				if (array == null || array.Length != m_frames.Count)
				{
					throw new InvalidOperationException("PackTextures failed for " + m_name);
				}
				((Texture)val).filterMode = (FilterMode)0;
				((Texture)val).wrapMode = (TextureWrapMode)1;
				((Object)val).name = m_name + "_tex";
				((Object)val).hideFlags = (HideFlags)32;
				for (int i = 0; i < array.Length; i++)
				{
					float num = ((Rect)(ref array[i])).width * (float)((Texture)val).width;
					float num2 = ((Rect)(ref array[i])).height * (float)((Texture)val).height;
					if (Mathf.Abs(num - (float)((Texture)m_frames[i]).width) > 0.5f || Mathf.Abs(num2 - (float)((Texture)m_frames[i]).height) > 0.5f)
					{
						throw new InvalidOperationException(m_name + ": frame " + i + " was resized by the packer");
					}
				}
				Material material = new Material(baseMaterial)
				{
					name = m_name + "_mat",
					mainTexture = (Texture)(object)val,
					hideFlags = (HideFlags)32
				};
				exAtlas val2 = ScriptableObject.CreateInstance<exAtlas>();
				((Object)val2).name = m_name;
				((Object)val2).hideFlags = (HideFlags)32;
				val2.texture = val;
				val2.material = material;
				val2.elements = (Element[])(object)new Element[m_frames.Count];
				for (int j = 0; j < m_frames.Count; j++)
				{
					val2.elements[j] = new Element
					{
						name = m_name + "_" + j,
						originalWidth = ((Texture)m_frames[j]).width,
						originalHeight = ((Texture)m_frames[j]).height,
						trimRect = new Rect(0f, 0f, (float)((Texture)m_frames[j]).width, (float)((Texture)m_frames[j]).height),
						coords = array[j],
						rotated = false
					};
				}
				Atlas = val2;
			}

			public exSpriteAnimClip Clip(string clipName, string key, float fps, WrapMode wrap, IEnumerable<EventInfo> events = null, int[] order = null)
			{
				//IL_0131: Unknown result type (might be due to invalid IL or missing references)
				//IL_0133: Unknown result type (might be due to invalid IL or missing references)
				//IL_013a: Unknown result type (might be due to invalid IL or missing references)
				if ((Object)(object)Atlas == (Object)null)
				{
					throw new InvalidOperationException("sheet " + m_name + " must be built before cutting clip " + clipName);
				}
				if (fps <= 0f)
				{
					throw new ArgumentOutOfRangeException("fps", clipName + ": fps must be positive");
				}
				int[] frames = Frames(key);
				if (order != null)
				{
					for (int i = 0; i < order.Length; i++)
					{
						int num = order[i];
						if (num < 0 || num >= frames.Length)
						{
							throw new ArgumentOutOfRangeException("order", clipName + ": frame " + num + " is outside strip " + key + " (" + frames.Length + " frames)");
						}
					}
					frames = order.Select((int num3) => frames[num3]).ToArray();
				}
				exSpriteAnimClip val = ScriptableObject.CreateInstance<exSpriteAnimClip>();
				((Object)val).name = clipName;
				((Object)val).hideFlags = (HideFlags)32;
				val.wrapMode = wrap;
				val.stopAction = (StopAction)0;
				val.speed = 1f;
				val.sampleRate = 60f;
				float num2 = (val.length = (float)frames.Length / fps);
				val.frameInfos = ((IEnumerable<int>)frames).Select((Func<int, FrameInfo>)((int index) => new FrameInfo
				{
					atlas = Atlas,
					index = index,
					length = 1f / fps
				})).ToList();
				val.eventInfos = (from e in events ?? Enumerable.Empty<EventInfo>()
					where e != null
					orderby e.time
					select e).ToList();
				foreach (EventInfo eventInfo in val.eventInfos)
				{
					if (eventInfo.time < 0f || eventInfo.time > num2 + 0.0001f)
					{
						throw new ArgumentOutOfRangeException(clipName + ": event " + eventInfo.methodName + " at " + eventInfo.time + " is outside the clip (" + num2 + " s)");
					}
				}
				return val;
			}
		}

		private sealed class RefEq : IEqualityComparer<object>
		{
			public new bool Equals(object a, object b)
			{
				return a == b;
			}

			public int GetHashCode(object o)
			{
				return RuntimeHelpers.GetHashCode(o);
			}
		}

		public static readonly string[] TrapStates = new string[6] { "inactive", "activate", "active", "action", "deactivate", "greyedOut" };

		private static readonly float[] TrapStateFps = new float[6] { 4f, 8f, 6f, 10f, 8f, 6f };

		private static readonly FieldInfo s_finalHeight = typeof(DepthHandler).GetField("m_finalHeightOffset", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		public static List<Texture2D> Slice(Texture2D strip, int frames)
		{
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Expected O, but got Unknown
			if (frames < 1 || ((Texture)strip).width % frames != 0)
			{
				throw new FormatException(((Object)strip).name + " is " + ((Texture)strip).width + " px wide, which does not divide into " + frames + " frames");
			}
			int num = ((Texture)strip).width / frames;
			List<Texture2D> list = new List<Texture2D>(frames);
			for (int i = 0; i < frames; i++)
			{
				Texture2D val = new Texture2D(num, ((Texture)strip).height, (TextureFormat)5, false)
				{
					filterMode = (FilterMode)0,
					wrapMode = (TextureWrapMode)1
				};
				val.SetPixels(strip.GetPixels(i * num, 0, num, ((Texture)strip).height));
				val.Apply();
				list.Add(val);
			}
			return list;
		}

		public static Material MaterialOf(string prefabName)
		{
			GameObject obj = Util.Prefab(prefabName);
			if ((Object)(object)obj == (Object)null)
			{
				throw new InvalidOperationException("prefab " + prefabName + " is not loaded");
			}
			exSprite component = obj.GetComponent<exSprite>();
			if ((Object)(object)component == (Object)null || (Object)(object)component.atlas == (Object)null || (Object)(object)component.atlas.material == (Object)null)
			{
				throw new InvalidOperationException(prefabName + " has no exSprite atlas material");
			}
			return component.atlas.material;
		}

		public static EventInfo Event(float time, string method)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: 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_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_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			return new EventInfo
			{
				time = time,
				methodName = method,
				paramType = (ParamType)0,
				msgOptions = (SendMessageOptions)1
			};
		}

		public static EventInfo Event(float time, string method, int value)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			EventInfo obj = Event(time, method);
			obj.paramType = (ParamType)3;
			obj.intParam = value;
			return obj;
		}

		public static EventInfo Event(float time, string method, float value)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			EventInfo obj = Event(time, method);
			obj.paramType = (ParamType)2;
			obj.floatParam = value;
			return obj;
		}

		public static EventInfo Event(float time, string method, string value)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			EventInfo obj = Event(time, method);
			obj.paramType = (ParamType)1;
			obj.stringParam = value ?? string.Empty;
			return obj;
		}

		public static EventInfo Sound(float time, AudioCue cue)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)cue == (Object)null)
			{
				return null;
			}
			EventInfo obj = Event(time, "AnimSound");
			obj.paramType = (ParamType)5;
			obj.objectParam = (Object)(object)((Component)cue).gameObject;
			return obj;
		}

		public static int SwapClips(GameObject root, Func<exSpriteAnimClip, exSpriteAnimClip> map)
		{
			int num = 0;
			HashSet<object> seen = new HashSet<object>(new RefEq());
			Component[] componentsInChildren = root.GetComponentsInChildren<Component>(true);
			foreach (Component val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null) && !(val is Transform))
				{
					num += Walk(val, map, seen, 0);
				}
			}
			return num;
		}

		private static int Walk(object o, Func<exSpriteAnimClip, exSpriteAnimClip> map, HashSet<object> seen, int depth)
		{
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Expected O, but got Unknown
			if (o == null || depth > 7 || !seen.Add(o))
			{
				return 0;
			}
			int num = 0;
			Type type = o.GetType();
			while ((object)type != null && (object)type != typeof(MonoBehaviour) && (object)type != typeof(Component) && (object)type != typeof(object))
			{
				FieldInfo[] fields = type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (FieldInfo fieldInfo in fields)
				{
					if (fieldInfo.IsStatic || fieldInfo.IsLiteral)
					{
						continue;
					}
					Type fieldType = fieldInfo.FieldType;
					if ((object)fieldType == typeof(exSpriteAnimClip))
					{
						object? value = fieldInfo.GetValue(o);
						exSpriteAnimClip val = (exSpriteAnimClip)((value is exSpriteAnimClip) ? value : null);
						if ((Object)(object)val != (Object)null)
						{
							exSpriteAnimClip val2 = map(val);
							if ((Object)(object)val2 != (Object)null && (Object)(object)val2 != (Object)(object)val)
							{
								fieldInfo.SetValue(o, val2);
								num++;
							}
						}
					}
					else if (typeof(IList).IsAssignableFrom(fieldType))
					{
						if (!(fieldInfo.GetValue(o) is IList list))
						{
							continue;
						}
						for (int j = 0; j < list.Count; j++)
						{
							object obj = list[j];
							if (obj is exSpriteAnimClip)
							{
								exSpriteAnimClip val3 = map((exSpriteAnimClip)obj);
								if ((Object)(object)val3 != (Object)null && val3 != obj)
								{
									list[j] = val3;
									num++;
								}
							}
							else if (obj != null && IsWalkable(obj.GetType()))
							{
								num += Walk(obj, map, seen, depth + 1);
							}
						}
					}
					else if (IsWalkable(fieldType))
					{
						num += Walk(fieldInfo.GetValue(o), map, seen, depth + 1);
					}
				}
				type = type.BaseType;
			}
			return num;
		}

		private static bool IsWalkable(Type t)
		{
			if (t.IsClass && !typeof(Object).IsAssignableFrom(t) && (object)t != typeof(string))
			{
				return t.IsDefined(typeof(SerializableAttribute), inherit: false);
			}
			return false;
		}

		public static int StripSoundEvents(GameObject root, string namePrefix)
		{
			Dictionary<exSpriteAnimClip, exSpriteAnimClip> copies = new Dictionary<exSpriteAnimClip, exSpriteAnimClip>();
			return SwapClips(root, (exSpriteAnimClip clip) => WithoutSoundEvents(clip, namePrefix, copies));
		}

		private static exSpriteAnimClip WithoutSoundEvents(exSpriteAnimClip clip, string prefix, Dictionary<exSpriteAnimClip, exSpriteAnimClip> copies)
		{
			if ((Object)(object)clip == (Object)null || clip.eventInfos == null || !clip.eventInfos.Any((EventInfo e) => e != null && e.methodName == "AnimSound"))
			{
				return clip;
			}
			if (!copies.TryGetValue(clip, out var value))
			{
				value = Object.Instantiate<exSpriteAnimClip>(clip);
				((Object)value).name = prefix + ((Object)clip).name;
				((Object)value).hideFlags = (HideFlags)32;
				value.eventInfos.RemoveAll((EventInfo e) => e != null && e.methodName == "AnimSound");
				copies[clip] = value;
			}
			return value;
		}

		public static GameObject CloneSilent(BossContext ctx, string prefabName, string newName)
		{
			GameObject obj = KitTemplates.Clone(prefabName, newName, ctx.Holder);
			StripSoundEvents(obj, newName);
			return obj;
		}

		public static bool HasSoundEvents(exSpriteAnimClip clip)
		{
			if ((Object)(object)clip != (Object)null && clip.eventInfos != null)
			{
				return clip.eventInfos.Any((EventInfo e) => e != null && e.methodName == "AnimSound");
			}
			return false;
		}

		public static AudioCueSource EnsureSoundReceiver(GameObject go, out bool added)
		{
			added = false;
			if ((Object)(object)go == (Object)null)
			{
				return null;
			}
			AudioCueSource val = go.GetComponent<AudioCueSource>();
			if ((Object)(object)val == (Object)null)
			{
				val = go.AddComponent<AudioCueSource>();
				val.m_playOnSpawn = null;
				val.m_stopOnDestroy = false;
				val.m_cues = new List<AudioCue>();
				added = true;
			}
			return val;
		}

		public static AudioCueSource EnsureSoundReceiver(GameObject go)
		{
			bool added;
			return EnsureSoundReceiver(go, out added);
		}

		internal static HashSet<exSpriteAnimClip> ClipsUnder(GameObject root)
		{
			HashSet<exSpriteAnimClip> set = new HashSet<exSpriteAnimClip>();
			if ((Object)(object)root != (Object)null)
			{
				SwapClips(root, delegate(exSpriteAnimClip c)
				{
					set.Add(c);
					return c;
				});
			}
			return set;
		}

		internal static int AddReceiversForKitSounds(GameObject root, HashSet<exSpriteAnimClip> vanillaClips, string namePrefix)
		{
			if ((Object)(object)root == (Object)null)
			{
				return 0;
			}
			List<GameObject> list = new List<GameObject>();
			exSpriteAnimation[] componentsInChildren = root.GetComponentsInChildren<exSpriteAnimation>(true);
			foreach (exSpriteAnimation val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).GetComponent<AudioCueSource>() != (Object)null) && val.animations != null && val.animations.Any((exSpriteAnimClip c) => (Object)(object)c != (Object)null && (vanillaClips == null || !vanillaClips.Contains(c)) && HasSoundEvents(c)))
				{
					list.Add(((Component)val).gameObject);
				}
			}
			if (list.Count == 0)
			{
				return 0;
			}
			SilenceVanillaClips(root, vanillaClips, namePrefix);
			foreach (GameObject item in list)
			{
				EnsureSoundReceiver(item);
			}
			return list.Count;
		}

		internal static int SilenceVanillaClips(GameObject root, HashSet<exSpriteAnimClip> vanillaClips, string namePrefix)
		{
			if ((Object)(object)root == (Object)null || vanillaClips == null || vanillaClips.Count == 0)
			{
				return 0;
			}
			Dictionary<exSpriteAnimClip, exSpriteAnimClip> copies = new Dictionary<exSpriteAnimClip, exSpriteAnimClip>();
			return SwapClips(root, (exSpriteAnimClip c) => (!vanillaClips.Contains(c)) ? c : WithoutSoundEvents(c, namePrefix, copies));
		}

		public static Dictionary<string, exSpriteAnimClip> TrapStateClips(Sheet sheet, string clipPrefix, float[] fps = null)
		{
			return TrapStateClips(sheet, clipPrefix, fps, null);
		}

		public static Dictionary<string, exSpriteAnimClip> TrapStateClips(Sheet sheet, string clipPrefix, float[] fps, IEnumerable<EventInfo> actionEvents)
		{
			if (sheet == null)
			{
				throw new ArgumentNullException("sheet");
			}
			if (fps != null && fps.Length != TrapStates.Length)
			{
				throw new ArgumentException("TrapStateClips needs " + TrapStates.Length + " fps values");
			}
			Dictionary<string, exSpriteAnimClip> dictionary = new Dictionary<string, exSpriteAnimClip>();
			for (int i = 0; i < TrapStates.Length; i++)
			{
				string text = TrapStates[i];
				string key = (sheet.Has(clipPrefix + "_" + text) ? (clipPrefix + "_" + text) : text);
				bool flag = text == "inactive" || text == "active";
				dictionary[text] = sheet.Clip(clipPrefix + "_" + text, key, (fps != null) ? fps[i] : TrapStateFps[i], (WrapMode)((!flag) ? 1 : 2), (text == "action") ? actionEvents : null);
			}
			return dictionary;
		}

		public static Dictionary<string, exSpriteAnimClip> TrapStateClips(ClipLibrary lib, string station)
		{
			if (lib == null)
			{
				throw new ArgumentNullException("lib");
			}
			Dictionary<string, exSpriteAnimClip> dictionary = new Dictionary<string, exSpriteAnimClip>();
			string[] trapStates = TrapStates;
			foreach (string text in trapStates)
			{
				dictionary[text] = lib[station + "_" + text];
			}
			return dictionary;
		}

		public static exSprite CreateSprite(Transform parent, Sheet sheet, string key, int frame, Vector3 world, Anchor anchor = (Anchor)7, bool depthSorted = true, float heightOffset = 0f)
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Expected O, but got Unknown
			//IL_0087: 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_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			if (sheet == null || (Object)(object)sheet.Atlas == (Object)null)
			{
				throw new InvalidOperationException("CreateSprite needs a built sheet");
			}
			int[] array = sheet.Frames(key);
			if (frame < 0 || frame >= array.Length)
			{
				throw new ArgumentOutOfRangeException("frame", key + " has " + array.Length + " frames");
			}
			GameObject val = new GameObject(sheet.Name + "_" + key);
			if ((Object)(object)parent != (Object)null)
			{
				val.transform.SetParent(parent, false);
			}
			val.transform.position = new Vector3(Mathf.Round(world.x), Mathf.Round(world.y), 0f);
			val.AddComponent<MeshFilter>();
			val.AddComponent<MeshRenderer>();
			exSprite obj = val.AddComponent<exSprite>();
			((exPlane)obj).anchor = anchor;
			obj.SetSprite(sheet.Atlas, array[frame], false);
			if (depthSorted)
			{
				DepthHandler val2 = val.AddComponent<DepthHandler>();
				val2.m_heightOffset = heightOffset;
				if ((object)s_finalHeight != null)
				{
					s_finalHeight.SetValue(val2, heightOffset);
				}
			}
			Room val3 = (((Object)(object)parent != (Object)null) ? ((Component)parent).GetComponentInParent<Room>() : null);
			if ((Object)(object)val3 != (Object)null)
			{
				KitRoom.MatchHidden(val3, val);
			}
			return obj;
		}

		public static exSpriteAnimation Animate(exSprite sprite, IEnumerable<exSpriteAnimClip> clips, exSpriteAnimClip defaultClip, bool play = true)
		{
			exSpriteAnimation val = ((Component)sprite).GetComponent<exSpriteAnimation>();
			if ((Object)(object)val == (Object)null)
			{
				val = ((Component)sprite).gameObject.AddComponent<exSpriteAnimation>();
			}
			List<exSpriteAnimClip> given = new List<exSpriteAnimClip>();
			if (clips != null)
			{
				given.AddRange(clips.Where((exSpriteAnimClip c) => (Object)(object)c != (Object)null));
			}
			if ((Object)(object)defaultClip != (Object)null)
			{
				given.Add(defaultClip);
			}
			if ((Object)(object)((Component)sprite).GetComponent<AudioCueSource>() == (Object)null && given.Any(HasSoundEvents))
			{
				List<string> list = ((val.animations != null) ? (from c in val.animations
					where (Object)(object)c != (Object)null && !given.Contains(c) && HasSoundEvents(c)
					select ((Object)c).name).ToList() : new List<string>());
				if (list.Count > 0)
				{
					Kit.Log.WarnOnce("animate receiver " + ((Object)sprite).name, ((Object)sprite).name + ": a sound receiver was added for the new clips, so the sound events of " + string.Join(", ", list.ToArray()) + " now play too");
				}
				EnsureSoundReceiver(((Component)sprite).gameObject);
			}
			foreach (exSpriteAnimClip item in given)
			{
				if ((Object)(object)item != (Object)(object)defaultClip)
				{
					val.AddAnimation(item);
				}
			}
			if ((Object)(object)defaultClip != (Object)null)
			{
				val.AddAnimation(defaultClip);
				val.defaultAnimation = defaultClip;
				if (play)
				{
					val.Play(defaultClip);
				}
			}
			return val;
		}

		public static void SetDepthOffset(GameObject go, float heightOffset)
		{
			DepthHandler val = (((Object)(object)go != (Object)null) ? go.GetComponent<DepthHandler>() : null);
			if (!((Object)(object)val == (Object)null))
			{
				val.m_heightOffset = heightOffset;
				if ((object)s_finalHeight != null)
				{
					s_finalHeight.SetValue(val, heightOffset);
				}
			}
		}

		public static void AddTint(GameObject go, Color c)
		{
			//IL_0000: 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)
			if (c.a > 0.6f)
			{
				throw new ArgumentException("tint alpha " + c.a + " is above 0.6 and would paint a flat silhouette");
			}
			ColorTinterBase val = go.GetComponent<ColorTinterBase>();
			if ((Object)(object)val == (Object)null)
			{
				val = go.AddComponent<ColorTinterBase>();
			}
			val.AddTint(c);
		}

		public static void RemoveTint(GameObject go, Color c)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			ColorTinterBase val = (((Object)(object)go != (Object)null) ? go.GetComponent<ColorTinterBase>() : null);
			if ((Object)(object)val != (Object)null)
			{
				val.RemoveTint(c);
			}
		}
	}
	public sealed class ClipLibrary
	{
		private sealed class Meta
		{
			public string Name;

			public int Frames;

			public float Fps;

			public WrapMode Wrap;

			public List<EventInfo> Events = new List<EventInfo>();
		}

		private readonly string m_prefix;

		private readonly Dictionary<string, Meta> m_meta = new Dictionary<string, Meta>();

		private readonly Dictionary<string, exSpriteAnimClip> m_clips = new Dictionary<string, exSpriteAnimClip>();

		private readonly List<string> m_order = new List<string>();

		public KitArt.Sheet Sheet { get; private set; }

		public exSpriteAnimClip this[string name]
		{
			get
			{
				if (!m_clips.TryGetValue(name, out var value))
				{
					throw new KeyNotFoundException("no clip " + name + " in " + m_prefix + ".clips.json (it has " + string.Join(", ", m_order.ToArray()) + ")");
				}
				return value;
			}
		}

		public IEnumerable<exSpriteAnimClip> All => m_order.Select((string n) => m_clips[n]);

		private ClipLibrary(string prefix)
		{
			m_prefix = prefix;
		}

		public static ClipLibrary Load(BossContext ctx, string prefix, Material baseMaterial, Func<string, AudioCue> cueFor)
		{
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_029a: Unknown result type (might be due to invalid IL or missing references)
			if (ctx == null)
			{
				throw new ArgumentNullException("ctx");
			}
			ClipLibrary clipLibrary = new ClipLibrary(prefix);
			if (!(MiniJson.Parse(ctx.Assets.Text(prefix + ".clips.json")) is MiniJson.JsonObject jsonObject))
			{
				throw new FormatException(prefix + ".clips.json: the top level must be an object");
			}
			foreach (string item in jsonObject.Keys2)
			{
				if (!(jsonObject[item] is MiniJson.JsonObject jsonObject2))
				{
					throw new FormatException(prefix + ".clips.json: " + item + " is not an object");
				}
				Meta meta = new Meta
				{
					Name = item
				};
				meta.Frames = (int)Num(jsonObject2, "frames", item, prefix);
				meta.Fps = (float)Num(jsonObject2, "fps", item, prefix);
				if (meta.Frames < 1 || meta.Fps <= 0f)
				{
					throw new FormatException(prefix + ".clips.json: " + item + " needs frames >= 1 and fps > 0");
				}
				meta.Wrap = (WrapMode)((!jsonObject2.TryGetValue("wrap", out var value) || value == null) ? 1 : ((int)ParseWrap(value.ToString(), item)));
				if (jsonObject2.TryGetValue("events", out var value2) && value2 != null)
				{
					foreach (object item2 in (value2 as List<object>) ?? throw new FormatException(prefix + ".clips.json: " + item + ".events must be an array"))
					{
						EventInfo val = ParseEvent(ctx, item2, item, prefix, cueFor);
						if (val != null)
						{
							meta.Events.Add(val);
						}
					}
				}
				clipLibrary.m_meta[item] = meta;
				clipLibrary.m_order.Add(item);
			}
			KitArt.Sheet sheet = new KitArt.Sheet(prefix);
			foreach (string item3 in clipLibrary.m_order)
			{
				sheet.AddStrip(item3, ctx.Assets, prefix + "." + item3 + ".png", clipLibrary.m_meta[item3].Frames);
			}
			sheet.Build(baseMaterial);
			clipLibrary.Sheet = sheet;
			foreach (string item4 in clipLibrary.m_order)
			{
				Meta meta2 = clipLibrary.m_meta[item4];
				clipLibrary.m_clips[item4] = sheet.Clip(prefix + item4, item4, meta2.Fps, meta2.Wrap, meta2.Events);
			}
			return clipLibrary;
		}

		private static double Num(MiniJson.JsonObject body, string field, string clip, string prefix)
		{
			if (!body.TryGetValue(field, out var value) || !(value is double))
			{
				throw new FormatException(prefix + ".clips.json: " + clip + " is missing the number " + field);
			}
			return (double)value;
		}

		private static WrapMode ParseWrap(string s, string clip)
		{
			return (WrapMode)(s.ToLowerInvariant() switch
			{
				"loop" => 2, 
				"once" => 1, 
				"pingpong" => 4, 
				"clampforever" => 8, 
				_ => throw new FormatException("clips.json: " + clip + " has an unknown wrap " + s), 
			});
		}

		private static EventInfo ParseEvent(BossContext ctx, object row, string clip, string prefix, Func<string, AudioCue> cueFor)
		{
			if (!(row is List<object> { Count: >=3 } list) || !(list[0] is double) || !(list[1] is string) || !(list[2] is string))
			{
				throw new FormatException(prefix + ".clips.json: " + clip + " has an event that is not [time, method, kind, value]");
			}
			float time = (float)(double)list[0];
			string text = (string)list[1];
			string text2 = ((string)list[2]).ToLowerInvariant();
			object obj = ((list.Count > 3) ? list[3] : null);
			switch (text2)
			{
			case "none":
				return KitArt.Event(time, text);
			case "int":
				if (!(obj is double))
				{
					throw new FormatException(prefix + ".clips.json: " + clip + " event " + text + " needs an int value");
				}
				return KitArt.Event(time, text, (int)Math.Round((double)obj));
			case "float":
				if (!(obj is double))
				{
					throw new FormatException(prefix + ".clips.json: " + clip + " event " + text + " needs a float value");
				}
				return KitArt.Event(time, text, (float)(double)obj);
			case "string":
				return KitArt.Event(time, text, (obj != null) ? obj.ToString() : string.Empty);
			case "sound":
			{
				string text3 = obj?.ToString();
				AudioCue val = null;
				try
				{
					val = ((text3 != null && cueFor != null) ? cueFor(text3) : null);
				}
				catch (Exception e)
				{
					ctx.Log.WarnOnce("cue " + text3, e);
				}
				if ((Object)(object)val == (Object)null)
				{
					ctx.Log.WarnOnce("nocue " + prefix + clip + text3, prefix + clip + ": no cue " + text3 + ", its sound event is dropped");
					return null;
				}
				EventInfo obj2 = KitArt.Sound(time, val);
				obj2.methodName = text;
				return obj2;
			}
			default:
				throw new FormatException(prefix + ".clips.json: " + clip + " event " + text + " has an unknown kind " + text2);
			}
		}

		public bool Has(string name)
		{
			return m_clips.ContainsKey(name);
		}

		public float Length(string name)
		{
			return this[name].length;
		}

		public exSpriteAnimClip Rebuild(string name, float? fps = null, WrapMode? wrap = null, IEnumerable<EventInfo> events = null, int[] order = null)
		{
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			if (!m_meta.TryGetValue(name, out var value))
			{
				throw new KeyNotFoundException("no clip " + name + " in " + m_prefix + ".clips.json");
			}
			exSpriteAnimClip val = Sheet.Clip(m_prefix + name, name, fps ?? value.Fps, (WrapMode)(((??)wrap) ?? value.Wrap), events ?? value.Events, order);
			m_clips[name] = val;
			return val;
		}
	}
	public sealed class BossAssets
	{
		private readonly Assembly m_asm;

		private readonly string[] m_names;

		public Assembly Assembly => m_asm;

		public BossAssets(Assembly asm)
		{
			if ((object)asm == null)
			{
				throw new ArgumentNullException("asm");
			}
			m_asm = asm;
			m_names = asm.GetManifestResourceNames();
		}

		private string Resolve(string logicalName, bool throwIfMissing)
		{
			if (m_names.Contains(logicalName))
			{
				return logicalName;
			}
			string[] array = m_names.Where((string n) => n.EndsWith("." + logicalName, StringComparison.OrdinalIgnoreCase)).ToArray();
			if (array.Length == 1)
			{
				return array[0];
			}
			if (!throwIfMissing)
			{
				return null;
			}
			if (array.Length > 1)
			{
				throw new FileNotFoundException("embedded resource " + logicalName + " is ambiguous in " + m_asm.GetName().Name + ": " + string.Join(", ", array));
			}
			throw new FileNotFoundException("embedded resource " + logicalName + " not found in " + m_asm.GetName().Name + " (it has " + m_names.Length + " resources" + ((m_names.Length != 0) ? (", e.g. " + string.Join(", ", m_names.Take(8).ToArray())) : "") + ")");
		}

		internal int Count(Func<string, bool> test)
		{
			return m_names.Count(test);
		}

		public bool Has(string logicalName)
		{
			return Resolve(logicalName, throwIfMissing: false) != null;
		}

		public byte[] Bytes(string logicalName)
		{
			string text = Resolve(logicalName, throwIfMissing: true);
			using Stream stream = m_asm.GetManifestResourceStream(text);
			if (stream == null)
			{
				throw new FileNotFoundException("embedded resource " + text + " could not be opened");
			}
			using MemoryStream memoryStream = new MemoryStream();
			byte[] array = new byte[8192];
			int count;
			while ((count = stream.Read(array, 0, array.Length)) > 0)
			{
				memoryStream.Write(array, 0, count);
			}
			return memoryStream.ToArray();
		}

		public string Text(string logicalName)
		{
			byte[] array = Bytes(logicalName);
			int num = ((array.Length >= 3 && array[0] == 239 && array[1] == 187 && array[2] == 191) ? 3 : 0);
			return Encoding.UTF8.GetString(array, num, array.Length - num);
		}

		public Texture2D Png(string logicalName)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: 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_0037: 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_0047: Expected O, but got Unknown
			Texture2D val = new Texture2D(2, 2, (TextureFormat)5, false);
			if (!val.LoadImage(Bytes(logicalName)))
			{
				throw new FormatException("could not decode " + logicalName);
			}
			((Texture)val).filterMode = (FilterMode)0;
			((Texture)val).wrapMode = (TextureWrapMode)1;
			((Object)val).name = logicalName;
			((Object)val).hideFlags = (HideFlags)32;
			return val;
		}

		public string[] Names(string prefix)
		{
			string p = prefix + ".";
			return m_names.Where((string n) => n.StartsWith(p, StringComparison.Ordinal)).ToArray();
		}
	}
	internal static class MiniJson
	{
		internal sealed class JsonObject : Dictionary<string, object>
		{
			public readonly List<string> Keys2 = new List<string>();
		}

		public static object Parse(string text)
		{
			int i = 0;
			object result = Value(text, ref i);
			Skip(text, ref i);
			if (i != text.Length)
			{
				throw new FormatException("json: unexpected text at " + i);
			}
			return result;
		}

		private static void Skip(string s, ref int i)
		{
			while (i < s.Length && char.IsWhiteSpace(s[i]))
			{
				i++;
			}
		}

		private static object Value(string s, ref int i)
		{
			Skip(s, ref i);
			if (i >= s.Length)
			{
				throw new FormatException("json: unexpected end");
			}
			switch (s[i])
			{
			case '{':
				return Obj(s, ref i);
			case '[':
				return Arr(s, ref i);
			case '"':
				return Str(s, ref i);
			case 't':
				Word(s, ref i, "true");
				return true;
			case 'f':
				Word(s, ref i, "false");
				return false;
			case 'n':
				Word(s, ref i, "null");
				return null;
			default:
				return Num(s, ref i);
			}
		}

		private static void Word(string s, ref int i, string w)
		{
			if (string.CompareOrdinal(s, i, w, 0, w.Length) != 0)
			{
				throw new FormatException("json: bad literal at " + i);
			}
			i += w.Length;
		}

		private static JsonObject Obj(string s, ref int i)
		{
			JsonObject jsonObject = new JsonObject();
			i++;
			Skip(s, ref i);
			if (i < s.Length && s[i] == '}')
			{
				i++;
				return jsonObject;
			}
			while (true)
			{
				Skip(s, ref i);
				if (i >= s.Length || s[i] != '"')
				{
					throw new FormatException("json: expected a key at " + i);
				}
				string text = Str(s, ref i);
				Skip(s, ref i);
				if (i >= s.Length || s[i] != ':')
				{
					throw new FormatException("json: expected ':' at " + i);
				}
				i++;
				object value = Value(s, ref i);
				if (!jsonObject.ContainsKey(text))
				{
					jsonObject.Keys2.Add(text);
				}
				jsonObject[text] = value;
				Skip(s, ref i);
				if (i >= s.Length || s[i] != ',')
				{
					break;
				}
				i++;
			}
			if (i < s.Length && s[i] == '}')
			{
				i++;
				return jsonObject;
			}
			throw new FormatException("json: expected ',' or '}' at " + i);
		}

		private static List<object> Arr(string s, ref int i)
		{
			List<object> list = new List<object>();
			i++;
			Skip(s, ref i);
			if (i < s.Length && s[i] == ']')
			{
				i++;
				return list;
			}
			while (true)
			{
				list.Add(Value(s, ref i));
				Skip(s, ref i);
				if (i >= s.Length || s[i] != ',')
				{
					break;
				}
				i++;
			}
			if (i < s.Length && s[i] == ']')
			{
				i++;
				return list;
			}
			throw new FormatException("json: expected ',' or ']' at " + i);
		}

		private static string Str(string s, ref int i)
		{
			StringBuilder stringBuilder = new StringBuilder();
			i++;
			while (i < s.Length)
			{
				char c = s[i++];
				switch (c)
				{
				case '"':
					return stringBuilder.ToString();
				default:
					stringBuilder.Append(c);
					continue;
				case '\\':
					break;
				}
				if (i >= s.Length)
				{
					break;
				}
				char c2 = s[i++];
				switch (c2)
				{
				case '"':
					stringBuilder.Append('"');
					break;
				case '\\':
					stringBuilder.Append('\\');
					break;
				case '/':
					stringBuilder.Append('/');
					break;
				case 'b':
					stringBuilder.Append('\b');
					break;
				case 'f':
					stringBuilder.Append('\f');
					break;
				case 'n':
					stringBuilder.Append('\n');
					break;
				case 'r':
					stringBuilder.Append('\r');
					break;
				case 't':
					stringBuilder.Append('\t');
					break;
				case 'u':
					if (i + 4 > s.Length)
					{
						throw new FormatException("json: bad \\u escape");
					}
					stringBuilder.Append((char)int.Parse(s.Substring(i, 4), NumberStyles.HexNumber, CultureInfo.InvariantCulture));
					i += 4;
					break;
				default:
					throw new FormatException("json: bad escape \\" + c2);
				}
			}
			throw new FormatException("json: unterminated string");
		}

		private static double Num(string s, ref int i)
		{
			int num = i;
			while (i < s.Length && "+-0123456789.eE".IndexOf(s[i]) >= 0)
			{
				i++;
			}
			if (i == num)
			{
				throw new FormatException("json: unexpected character '" + s[i] + "' at " + i);
			}
			return double.Parse(s.Substring(num, i - num), NumberStyles.Float, CultureInfo.InvariantCulture);
		}
	}
	public sealed class BodySpec
	{
		public ClipLibrary Clips;

		public string Idle;

		public string Run;

		public string Dead;

		public string Statue;

		public float HealthMax;

		public float Resistance = 1f;

		public float VulnerableMult = 1f;

		public float MaxDamagePerHit;

		public eAllowedDamageSource AllowedDamage;

		public float Speed;

		public float Mass = 600f;

		public float KnockbackSpeed;

		public AudioCue DieSound;

		public Vector2 AttackSpawnNode;

		public List<AttackData> Attacks;

		public List<DamageEffectData> Effects;

		public int CapsuleDirection;

		public float CapsuleRadius;

		public float CapsuleHeight;

		public Vector3 CapsuleCenter;

		public Vector3 HitZoneScale;

		public Vector3 HitZonePos;

		public Vector2 SpriteOffset;

		public Anchor Anchor = (Anchor)7;
	}
	public static class KitBodies
	{
		private static readonly Dictionary<int, BodySpec> s_specs = new Dictionary<int, BodySpec>();

		internal static readonly Dictionary<int, KitBoss> KeptInRoom = new Dictionary<int, KitBoss>();

		internal static BodySpec SpecOf(GameObject template)
		{
			if (!((Object)(object)template != (Object)null) || !s_specs.TryGetValue(((Object)template).GetInstanceID(), out var value))
			{
				return null;
			}
			return value;
		}

		public static GameObject CloneBody(BossContext ctx, string vanillaEnemy, string newName, BodySpec spec)
		{
			//IL_02c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0381: Unknown result type (might be due to invalid IL or missing references)
			//IL_0406: Unknown result type (might be due to invalid IL or missing references)
			//IL_040b: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0566: Unknown result type (might be due to invalid IL or missing references)
			//IL_0573: Unknown result type (might be due to invalid IL or missing references)
			//IL_046c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0490: Unknown result type (might be due to invalid IL or missing references)
			//IL_049a: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_04bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_04cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_04cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0513: Unknown result type (might be due to invalid IL or missing references)
			//IL_0545: Unknown result type (might be due to invalid IL or missing references)
			//IL_0559: Unknown result type (might be due to invalid IL or missing references)
			if (ctx == null || spec == null)
			{
				throw new ArgumentNullException((ctx == null) ? "ctx" : "spec");
			}
			if (spec.Clips == null || string.IsNullOrEmpty(spec.Idle) || string.IsNullOrEmpty(spec.Run) || string.IsNullOrEmpty(spec.Dead))
			{
				throw new ArgumentException(newName + ": BodySpec needs Clips, Idle, Run and Dead");
			}
			if (spec.HealthMax <= 0f)
			{
				throw new ArgumentException(newName + ": BodySpec.HealthMax must be positive");
			}
			if (spec.Resistance <= 0f)
			{
				throw new ArgumentException(newName + ": BodySpec.Resistance must be positive (damage is divided by it)");
			}
			if (spec.Effects != null && spec.AttackSpawnNode.x != 0f && spec.Effects.Any((DamageEffectData e) => e != null && !e.m_rotateOffsetX))
			{
				throw new ArgumentException(newName + ": an effect with m_rotateOffsetX false needs AttackSpawnNode.x 0 (Attacks.cs:623-640)");
			}
			exSpriteAnimClip val = spec.Clips[spec.Idle];
			exSpriteAnimClip value = spec.Clips[spec.Run];
			exSpriteAnimClip value2 = spec.Clips[spec.Dead];
			exSpriteAnimClip value3 = (string.IsNullOrEmpty(spec.Statue) ? val : spec.Clips[spec.Statue]);
			if (val.frameInfos == null || val.frameInfos.Count == 0)
			{
				throw new InvalidOperationException(newName + ": the Idle clip has no frames");
			}
			GameObject val2 = KitTemplates.Clone(vanillaEnemy, newName, ctx.Holder);
			Player o = Need<Player>(val2, vanillaEnemy);
			Health o2 = Need<Health>(val2, vanillaEnemy);
			PlayerMovement o3 = Need<PlayerMovement>(val2, vanillaEnemy);
			Rigidbody val3 = Need<Rigidbody>(val2, vanillaEnemy);
			exSprite val4 = Need<exSprite>(val2, vanillaEnemy);
			exSpriteAnimation val5 = Need<exSpriteAnimation>(val2, vanillaEnemy);
			HashSet<exSpriteAnimClip> vanillaClips = KitArt.ClipsUnder(val2);
			PlayerAI[] components = val2.GetComponents<PlayerAI>();
			for (int num = 0; num < components.Length; num++)
			{
				Object.DestroyImmediate((Object)(object)components[num]);
			}
			if ((Object)(object)val2.GetComponent<PlayerAI>() != (Object)null)
			{
				throw new InvalidOperationException(vanillaEnemy + ": its PlayerAI could not be removed");
			}
			Util.Set(o, "m_animationIdle", val);
			Util.Set(o, "m_animationRun", value);
			Util.Set(o, "m_animationDead", value2);
			Util.Set(o, "m_animationStatue", value3);
			Util.Set(o, "m_animationKnockback", null);
			Util.Set(o, "m_animationSpawn", null);
			Util.Set(o, "m_hasSpecialAttack", false);
			Util.Set(o, "m_spawnOnDeath", new DamageEffectData[0]);
			Util.Set(o, "m_knockbackSpeed", spec.KnockbackSpeed);
			Util.Set(o, "m_knockbackCancelsAttack", false);
			Util.Set(o, "m_soundHit", null);
			Util.Set(o, "m_soundDie", spec.DieSound);
			Util.Set(o, "m_attackSpawnNode", spec.AttackSpawnNode);
			Util.Set(o, "m_attacks", (spec.Attacks != null) ? new List<AttackData>(spec.Attacks) : new List<AttackData>());
			Util.Set(o, "m_attackDamageEffects", (spec.Effects != null) ? new List<DamageEffectData>(spec.Effects) : new List<DamageEffectData>());
			Util.Set(o2, "m_healthMax", spec.HealthMax);
			Util.Set(o2, "m_damageResistance", spec.Resistance);
			Util.Set(o2, "m_vulnerableDamageMult", spec.VulnerableMult);
			Util.Set(o2, "m_vulnerableState", string.Empty);
			Util.Set(o2, "m_allowedDamageSource", spec.AllowedDamage);
			if (spec.Speed > 0f)
			{
				Util.Set(o3, "m_speedMax", spec.Speed);
			}
			val3.mass = spec.Mass;
			if (spec.CapsuleRadius > 0f)
			{
				CapsuleCollider obj = Need<CapsuleCollider>(val2, vanillaEnemy);
				obj.direction = spec.CapsuleDirection;
				obj.radius = spec.CapsuleRadius;
				obj.height = spec.CapsuleHeight;
				obj.center = spec.CapsuleCenter;
			}
			if (spec.HitZoneScale != Vector3.zero)
			{
				Transform obj2 = val2.transform.Find("HitZone");
				if ((Object)(object)obj2 == (Object)null)
				{
					throw new InvalidOperationException(vanillaEnemy + " has no HitZone child");
				}
				BoxCollider component = ((Component)obj2).GetComponent<BoxCollider>();
				if ((Object)(object)component == (Object)null)
				{
					throw new InvalidOperationException(vanillaEnemy + ": its HitZone has no BoxCollider, so HitZoneScale has no defined size");
				}
				component.size = new Vector3((component.size.x < 0f) ? (-1f) : 1f, 1f, component.size.z);
				component.center = new Vector3(0f, 0f, component.center.z);
				Vector3 localScale = obj2.localScale;
				Vector3 localPosition = obj2.localPosition;
				obj2.localScale = new Vector3(spec.HitZoneScale.x, spec.HitZoneScale.y, (spec.HitZoneScale.z != 0f) ? spec.HitZoneScale.z : localScale.z);
				obj2.localPosition = new Vector3(spec.HitZonePos.x, spec.HitZonePos.y, (spec.HitZonePos.z != 0f) ? spec.HitZonePos.z : localPosition.z);
			}
			((exPlane)val4).anchor = spec.Anchor;
			((exPlane)val4).offset = spec.SpriteOffset;
			exAtlas atlas = val.frameInfos[0].atlas;
			val4.SetSprite(atlas, val.frameInfos[0].index, true);
			val5.animations = new List<exSpriteAnimClip>();
			foreach (exSpriteAnimClip item in spec.Clips.All)
			{
				if (item.frameInfos.Count > 0 && (Object)(object)item.frameInfos[0].atlas == (Object)(object)atlas)
				{
					val5.AddAnimation(item);
				}
			}
			val5.defaultAnimation = val;
			val5.playAutomatically = false;
			AudioCueSource[] componentsInChildren = val2.GetComponentsInChildren<AudioCueSource>(true);
			for (int num = 0; num < componentsInChildren.Length; num++)
			{
				componentsInChildren[num].m_playOnSpawn = null;
			}
			if ((Object)(object)val2.GetComponent<AudioCueSource>() == (Object)null && spec.Clips.All.Any(KitArt.HasSoundEvents))
			{
				KitArt.SilenceVanillaClips(val2, vanillaClips, newName + "_");
				KitArt.EnsureSoundReceiver(val2);
			}
			s_specs[((Object)val2).GetInstanceID()] = spec;
			ctx.BodySpecs.Add(spec);
			return val2;
		}

		private static T Need<T>(GameObject go, string what) where T : Component
		{
			T component = go.GetComponent<T>();
			if ((Object)(object)component == (Object)null)
			{
				throw new InvalidOperationException(what + " has no " + typeof(T).Name);
			}
			return component;
		}

		public static KitBody Spawn<TBrain>(KitBoss boss, GameObject bodyTemplate, Vector2 roomLocal, string name) where TBrain : KitBrain
		{
			//IL_006c: 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_0072: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)boss == (Object)null || (Object)(object)boss.Arena == (Object)null)
			{
				throw new InvalidOperationException("KitBodies.Spawn needs a live KitBoss in its arena");
			}
			if ((Object)(object)SystemLevel.GetCurrentRoom() != (Object)(object)boss.Arena)
			{
				throw new InvalidOperationException("KitBodies.Spawn(" + name + ") while the arena is not the current room: the body would despawn (R7)");
			}
			BodySpec bodySpec = SpecOf(bodyTemplate);
			if (bodySpec == null)
			{
				throw new InvalidOperationException("KitBodies.Spawn(" + name + "): the template was not made by KitBodies.CloneBody");
			}
			GameObject val = ExtentionsMethodsPool.Spawn(bodyTemplate, boss.World(roomLocal), Quaternion.identity);
			if ((Object)(object)val == (Object)null)
			{
				throw new InvalidOperationException("spawning " + name + " failed");
			}
			((Object)val).name = name;
			if ((Object)(object)val.transform.parent != (Object)null)
			{
				val.transform.SetParent((Transform)null, true);
			}
			TBrain val2 = val.AddComponent<TBrain>();
			if ((Object)(object)val.GetComponent<PlayerAI>() != (Object)(object)val2)
			{
				Object.Destroy((Object)(object)val2);
				ExtentionsMethodsPool.Despawn(val);
				throw new InvalidOperationException("KitBodies.Spawn(" + name + "): the body carries another PlayerAI, the brain would be ignored");
			}
			KitBody kitBody = val.AddComponent<KitBody>();
			kitBody.Setup(boss, bodySpec, val2);
			val.GetComponent<Player>().InitAsAI((GameObject)null);
			kitBody.AfterInit();
			boss.TrackRoot(val);
			return kitBody;
		}
	}
	public sealed class KitBody : MonoBehaviour
	{
		internal static readonly Dictionary<int, KitBody> ByPlayer = new Dictionary<int, KitBody>();

		internal static readonly Dictionary<int, KitBody> ByMovement = new Dictionary<int, KitBody>();

		internal static readonly Dictionary<int, KitBody> ByGameObject = new Dictionary<int, KitBody>();

		private bool m_dead;

		private bool m_registered;

		public bool KeepInRoom = true;

		public bool GuardStuns = true;

		public bool RefuseStatuses;

		internal bool AllowStun;

		private bool m_holdVulnerable;

		private readonly Dictionary<string, float> m_scales = new Dictionary<string, float>();

		private AudioCue m_hurt;

		private float m_hurtGap = 0.25f;

		private float m_lastHurt = -10f;

		public Func<Vector3?> VelocityOverride;

		private int m_cutsceneId;

		public KitBoss Boss { get; private set; }

		public Player Player { get; private set; }

		public Health Health { get; private set; }

		public PlayerMovement Movement { get; private set; }

		public KitBrain Brain { get; private set; }

		public exSpriteAnimation Anim { get; private set; }

		public Rigidbody Body { get; private set; }

		public bool IsLife { get; internal set; }

		internal BodySpec Spec { get; private set; }

		public bool Alive
		{
			get
			{
				if (!m_dead && (Object)(object)Health != (Object)null)
				{
					return Health.IsAlive();
				}
				return false;
			}
		}

		public bool HoldVulnerable
		{
			get
			{
				return m_holdVulnerable;
			}
			set
			{
				if (m_holdVulnerable != value)
				{
					m_holdVulnerable = value;
					SetVulnerable(value);
				}
			}
		}

		public event Action<DamageInfo> Damaged;

		public event Action<DamageInfo> Died;

		public void Stun(float time, exSpriteAnimClip loopClip = null)
		{
			if (Alive)
			{
				AllowStun = true;
				try
				{
					Player.Stun(time, false);
				}
				finally
				{
					AllowStun = false;
				}
				if ((Object)(object)loopClip != (Object)null && (Object)(object)Anim != (Object)null)
				{
					Anim.Play(loopClip);
				}
			}
		}

		public void SetVulnerable(bool on)
		{
			if (!((Object)(object)Health == (Object)null) && (!on || Alive))
			{
				if (on)
				{
					Health.AnimVulnerableOn();
				}
				else
				{
					Health.AnimVulnerableOff();
				}
			}
		}

		public void ScaleEffect(GameObject fxTemplate, float scale)
		{
			if (!((Object)(object)fxTemplate == (Object)null))
			{
				if (scale <= 0f || Mathf.Approximately(scale, 1f))
				{
					m_scales.Remove(((Object)fxTemplate).name);
				}
				else
				{
					m_scales[((Object)fxTemplate).name] = scale;
				}
			}
		}

		public void SetHurtSound(AudioCue cue, float gap = 0.25f)
		{
			m_hurt = cue;
			m_hurtGap = gap;
		}

		internal void Setup(KitBoss boss, BodySpec spec, KitBrain brain)
		{
			Boss = boss;
			Spec = spec;
			Player = ((Component)this).GetComponent<Player>();
			Health = ((Component)this).GetComponent<Health>();
			Movement = ((Component)this).GetComponent<PlayerMovement>();
			Brain = brain;
			Anim = ((Component)this).GetComponent<exSpriteAnimation>();
			Body = ((Component)this).GetComponent<Rigidbody>();
			if ((Object)(object)Player != (Object)null)
			{
				ByPlayer[((Object)Player).GetInstanceID()] = this;
			}
			if ((Object)(object)Movement != (Object)null)
			{
				ByMovement[((Object)Movement).GetInstanceID()] = this;
			}
			ByGameObject[((Object)((Component)this).gameObject).GetInstanceID()] = this;
			m_registered = true;
		}

		internal void AfterInit()
		{
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			if (Spec != null && Spec.MaxDamagePerHit > 0f)
			{
				Health.SetMaxDamagePerHit(Spec.MaxDamagePerHit);
			}
			float multiplier = 1f;
			try
			{
				multiplier = SystemBalance.BossResistanceMultiplier;
			}
			catch (Exception e)
			{
				Kit.Log.WarnOnce("boss resistance multiplier", e);
			}
			Health.ModifyDamageResistance(Util.BossStack(multiplier));
			Player.CallbackOnDie = (Action<Player, DamageInfo>)Delegate.Combine(Player.CallbackOnDie, new Action<Player, DamageInfo>(OnDie));
			if ((Object)(object)Brain != (Object)null)
			{
				Brain.SetMove(Vector2.right, 0f);
			}
		}

		private void OnDie(Player p, DamageInfo info)
		{
			if (m_dead)
			{
				return;
			}
			m_dead = true;
			m_holdVulnerable = false;
			try
			{
				((MonoBehaviour)this).StopAllCoroutines();
				if ((Object)(object)Movement != (Object)null)
				{
					Movement.ResetInputOverride();
					Movement.ResetSpeedMultiplier();
				}
				if ((Object)(object)Brain != (Object)null)
				{
					Brain.Stop();
				}
			}
			catch (Exception e)
			{
				Kit.Log.WarnOnce("body die " + ((Object)this).name, e);
			}
			Action<DamageInfo> action = this.Died;
			if (action == null)
			{
				return;
			}
			try
			{
				action(info);
			}
			catch (Exception e2)
			{
				Kit.Log.WarnOnce("body died event " + ((Object)this).name, e2);
			}
		}

		private void OnDamaged(DamageInfo info)
		{
			if (m_dead || (Object)(object)Health == (Object)null)
			{
				return;
			}
			try
			{
				if ((Object)(object)m_hurt != (Object)null && info != null && info.m_source != null && info.m_source.m_sourcePlayer != null && (info.m_amount != 0f || (Object)(object)info.m_status != (Object)null || info.m_stunTime > 0f) && Time.time - m_lastHurt >= m_hurtGap)
				{
					m_lastHurt = Time.time;
					Util.PlaySound(m_hurt, ((Component)this).transform);
				}
			}
			catch (Exception e)
			{
				Kit.Log.WarnOnce("hurt sound " + ((Object)this).name, e);
			}
			Action<DamageInfo> action = this.Damaged;
			if (action == null)
			{
				return;
			}
			try
			{
				action(info);
			}
			catch (Exception e2)
			{
				Kit.Log.WarnOnce("body damaged event " + ((Object)this).name, e2);
			}
		}

		private void MsgOnObjectSpawn(GameObject obj)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)obj == (Object)null) && m_scales.Count != 0 && m_scales.TryGetValue(Util.StripClone(((Object)obj).name), out var value))
			{
				Vector3 localScale = obj.transform.localScale;
				obj.transform.localScale = new Vector3(Mathf.Sign((localScale.x == 0f) ? 1f : localScale.x) * value, value, 1f);
			}
		}

		private void Update()
		{
			if (m_holdVulnerable && Alive && (Object)(object)Health != (Object)null)
			{
				try
				{
					Health.AnimVulnerableOn();
				}
				catch (Exception e)
				{
					Kit.Log.WarnOnce("hold vulnerable " + ((Object)this).name, e);
				}
			}
		}

		public void Freeze(bool frozen)
		{
			if (frozen && (Object)(object)Brain != (Object)null)
			{
				Brain.Stop();
			}
		}

		public void PlayStatus(exSpriteAnimClip clip)
		{
			if (Alive && (Object)(object)clip != (Object)null)
			{
				Player.StartStatusAnimation(clip);
			}
		}

		public void PlayCutscene(exSpriteAnimClip clip, bool collisionOff = false)
		{
			if (Alive && !((Object)(object)clip == (Object)null))
			{
				HoldCutscene(clip, clip.length, collisionOff);
			}
		}

		public void HoldCutscene(exSpriteAnimClip clip, float holdSeconds, bool collisionOff = false)
		{
			if (Alive && !((Object)(object)clip == (Object)null))
			{
				int id = ++m_cutsceneId;
				Player.StartCutscene(clip, collisionOff, 0f);
				if (holdSeconds > 0f)
				{
					((MonoBehaviour)this).StartCoroutine(EndCutsceneAfter(holdSeconds, id));
				}
			}
		}

		public void CancelCutsceneEnd()
		{
			m_cutsceneId++;
		}

		private IEnumerator EndCutsceneAfter(float t, int id)
		{
			IEnumerator wait = KitBoss.WaitGameTime(t);
			while (wait.MoveNext())
			{
				yield return wait.Current;
			}
			if (id == m_cutsceneId && Alive && (int)Player.GetState() == 13)
			{
				Player.EndCutscene();
			}
		}

		public void EndAction()
		{
			//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_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Invalid comparison between Unknown and I4
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Invalid comparison between Unknown and I4
			m_cutsceneId++;
			if (Alive)
			{
				ePlayerState state = Player.GetState();
				if ((int)state == 15 || (int)state == 13)
				{
					Player.EndCutscene();
				}
			}
		}

		private void OnDestroy()
		{
			if (m_registered)
			{
				if ((Object)(object)Player != (Object)null)
				{
					ByPlayer.Remove(((Object)Player).GetInstanceID());
				}
				if ((Object)(object)Movement != (Object)null)
				{
					ByMovement.Remove(((Object)Movement).GetInstanceID());
				}
				ByGameObject.Remove(((Object)((Component)this).gameObject).GetInstanceID());
				m_registered = false;
			}
		}
	}
	public class KitBrain : PlayerAI
	{
		private static readonly FieldRef<PlayerAI, Vector2> s_face = AccessTools.FieldRefAccess<PlayerAI, Vector2>("m_faceDirection");

		private static readonly FieldRef<PlayerAI, float> s_move = AccessTools.FieldRefAccess<PlayerAI, float>("m_moveRatio");

		public int RequestedAttack = -1;

		public void SetMove(Vector2 dir, float ratio)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			if (((Vector2)(ref dir)).sqrMagnitude > 0.0001f)
			{
				s_face.Invoke((PlayerAI)(object)this) = ((Vector2)(ref dir)).normalized;
			}
			s_move.Invoke((PlayerAI)(object)this) = Mathf.Clamp01(ratio);
		}

		public void Face(Vector2 dir)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			SetMove(dir, 0f);
			if (((Vector2)(ref dir)).sqrMagnitude > 0.0001f)
			{
				PlayerMovement component = ((Component)this).GetComponent<PlayerMovement>();
				if ((Object)(object)component != (Object)null)
				{
					component.SetDirection(((Vector2)(ref dir)).normalized);
				}
			}
		}

		public void Stop()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			SetMove(Vector2.zero, 0f);
			RequestedAttack = -1;
		}

		public bool RequestAttack(int index)
		{
			Player component = ((Component)this).GetComponent<Player>();
			Health component2 = ((Component)this).GetComponent<Health>();
			if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null || !component2.IsAlive())
			{
				return false;
			}
			List<AttackData> list;
			try
			{
				list = Util.Get<List<AttackData>>(component, "m_attacks");
			}
			catch (Exception e)
			{
				Kit.Log.WarnOnce("request attack", e);
				return false;
			}
			if (list == null || index < 0 || index >= list.Count)
			{
				return false;
			}
			RequestedAttack = index;
			return true;
		}

		public override int GetAttackToStart()
		{
			return RequestedAttack;
		}

		public override void OnAttack()
		{
			RequestedAttack = -1;
		}

		private void Update()
		{
		}
	}
	public static class KitFx
	{
		public static GameObject CloneDamage(BossContext ctx, string prefabName, string newName, bool stripSounds = true)
		{
			GameObject obj = (stripSounds ? KitArt.CloneSilent(ctx, prefabName, newName) : KitTemplates.Clone(prefabName, newName, ctx.Holder));
			if ((Object)(object)obj.GetComponent<DamageEffect>() == (Object)null)
			{
				throw new InvalidOperationException(prefabName + " has no DamageEffect");
			}
			return obj;
		}

		public static GameObject TuneDamage(GameObject fx, float damage, float rate, float knockback, float stun)
		{
			DamageEffect obj = (((Object)(object)fx != (Object)null) ? fx.GetComponent<DamageEffect>() : null);
			if ((Object)(object)obj == (Object)null)
			{
				throw new InvalidOperationException((((Object)(object)fx != (Object)null) ? ((Object)fx).name : "null") + " has no DamageEffect");
			}
			Util.Set(obj, "m_damage", damage);
			Util.Set(obj, "m_damageRate", rate);
			Util.Set(obj, "m_knockbackMultiplier", knockback);
			Util.Set(obj, "m_stunTime", stun);
			return fx;
		}

		public static void SetLifetime(GameObject fx, float destroyAfter, bool destroyOnAnimEnd)
		{
			Effect obj = (((Object)(object)fx != (Object)null) ? fx.GetComponent<Effect>() : null);
			if ((Object)(object)obj == (Object)null)
			{
				throw new InvalidOperationException((((Object)(object)fx != (Object)null) ? ((Object)fx).name : "null") + " has no Effect");
			}
			Util.Set(obj, "m_destroyAfterTime", destroyAfter);
			Util.Set(obj, "m_destroyOnAnimEnd", destroyOnAnimEnd);
		}

		public static void SetNullifyable(GameObject fx, bool on)
		{
			DamageEffect obj = (((Object)(object)fx != (Object)null) ? fx.GetComponent<DamageEffect>() : null);
			if ((Object)(object)obj == (Object)null)
			{
				throw new InvalidOperationException((((Object)(object)fx != (Object)null) ? ((Object)fx).name : "null") + " has no DamageEffect");
			}
			Util.Set(obj, "m_nullifyable", on);
		}

		public static DamageEffectData EffectData(GameObject obj, bool attach, float offsetX, float offsetY)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: 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_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: 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_002d: Expected O, but got Unknown
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Expected O, but got Unknown
			return new DamageEffectData
			{
				m_object = obj,
				m_attach = attach,
				m_detatchOnAnimEnd = false,
				m_destroyOnAnimEnd = attach,
				m_offsetX = new MinMaxRange(offsetX),
				m_offsetY = new MinMaxRange(offsetY),
				m_rotateOffsetX = true,
				m_spawnPoint = (eSpawnPoint)0
			};
		}

		public static AttackData Attack(exSpriteAnimClip clip, float cooldown, float botInner, float botOuter)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: 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_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: 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_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: 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_005b: Expected O, but got Unknown
			//IL_005c: Expected O, but got Unknown
			return new AttackData
			{
				m_animationFront = clip,
				m_sound = null,
				m_cooldown = cooldown,
				m_moveInputRatioMin = 0f,
				m_moveInputRatioMax = 0f,
				m_pushOnContact = 0f,
				m_stopOnContact = false,
				m_botData = new BotAttackData
				{
					m_rangeInner = botInner,
					m_rangeOuter = botOuter
				}
			};
		}

		public static GameObject SpawnOwned(GameObject fxPrefab, Vector2 world, float angleDeg, GameObject owner, bool bossDamage = true)
		{
			//IL_000d: 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_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Expected O, but got Unknown
			if ((Object)(object)fxPrefab == (Object)null)
			{
				return null;
			}
			try
			{
				GameObject val = ExtentionsMethodsPool.SpawnBegin(fxPrefab, new Vector3(world.x, world.y, 0f), Quaternion.Euler(0f, 0f, angleDeg));
				if ((Object)(object)val == (Object)null)
				{
					return null;
				}
				ValueModifierStack val2 = null;
				if (bossDamage)
				{
					val2 = Util.BossStack(SystemBalance.BossDamageMultiplier);
				}
				val.SendMessage(Constants.MSG_SETSPAWNER, (object)new DamageSource(val, owner, (PlayerData)null, -1, -1, val2, false), (SendMessageOptions)1);
				ExtentionsMethodsPool.SpawnFinalize(val);
				return val;
			}
			catch (Exception e)
			{
				Kit.Log.WarnOnce("spawn owned " + ((Object)fxPrefab).name, e);
				return null;
			}
		}

		public static GameObject SpawnFx(GameObject prefab, Vector2 world, float angleDeg = 0f)
		{
			//IL_000d: 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_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)prefab == (Object)null)
			{
				return null;
			}
			try
			{
				return ExtentionsMethodsPool.Spawn(prefab, new Vector3(world.x, world.y, 0f), Quaternion.Euler(0f, 0f, angleDeg));
			}
			catch (Exception e)
			{
				Kit.Log.WarnOnce("fx " + ((Object)prefab).name, e);
				return null;
			}
		}
	}
	public sealed class BossBar : MonoBehaviour
	{
		public const float Z = -100f;

		public const float HalfHeight = 3.5f;

		private static readonly FieldInfo s_showTimer = typeof(GUIHealthBar).GetField("m_showTimer", BindingFlags.Instance | BindingFlags.NonPublic);

		public static GameObject Template { get; private set; }

		public GUIHealthBar Gui { get; private set; }

		public float BottomWorld => ((Component)this).transform.position.y - 3.5f;

		internal static void BuildTemplate(Transform holder)
		{
			try
			{
				GameObject val = Util.Prefab("BossHydra");
				Transform val2 = (((Object)(object)val != (Object)null) ? val.transform.Find("GUIHealthBar") : null);
				if ((Object)(object)val2 == (Object)null || (Object)(object)((Component)val2).GetComponent<GUIHealthBar>() == (Object)null)
				{
					throw new InvalidOperationException("BossHydra has no GUIHealthBar child");
				}
				GameObject obj = KitTemplates.CloneObject(((Component)val2).gameObject, "KitBossBar", holder);
				GUIHealthBar component = obj.GetComponent<GUIHealthBar>();
				component.m_health = null;
				if ((Object)(object)component.m_container != (Object)null)
				{
					component.m_container.SetActive(false);
				}
				Template = obj;
			}
			catch (Exception ex)
			{
				Template = null;
				Kit.Log.Warn("No top boss bar for kit bosses, they keep the bar over their heads: " + ex.Message);
			}
		}

		public static BossBar Spawn(KitBoss owner, Health health, Vector2 roomLocal)
		{
			//IL_0093: 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_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Template == (Object)null || (Object)(object)owner == (Object)null || (Object)(object)health == (Object)null)
			{
				return null;
			}
			try
			{
				GameObject obj = Object.Instantiate<GameObject>(Template);
				((Object)obj).name = ((owner.Ctx != null) ? (owner.Ctx.Info.TemplateName + "Bar") : "KitBossBar");
				obj.transform.SetParent(((Component)owner).transform, false);
				Vector3 val = (((Object)(object)owner.Arena != (Object)null) ? ((Component)owner.Arena).transform.position : ((Component)owner).transform.position);
				obj.transform.position = new Vector3(val.x + roomLocal.x, val.y + roomLocal.y, -100f);
				GUIHealthBar component = obj.GetComponent<GUIHealthBar>();
				component.SetHealthComponent(health);
				BossBar bossBar = obj.AddComponent<BossBar>();
				bossBar.Gui = component;
				Player component2 = ((Component)health).GetComponent<Player>();
				GUIHealthBar val2 = (((Object)(object)component2 != (Object)null) ? component2.GetGUIHealthBar() : null);
				if ((Object)(object)val2 != (Object)null)
				{
					val2.SetForceHidden(true);
				}
				return bossBar;
			}
			catch (Exception e)
			{
				Kit.Log.WarnOnce("boss bar", e);
				return null;
			}
		}

		public void KeepLit()
		{
			if (!((Object)(object)Gui == (Object)null) && (object)s_showTimer != null)
			{
				s_showTimer.SetValue(Gui, Gui.m_showTime + 0.1f);
			}
		}

		public void Hide()
		{
			if ((Object)(object)Gui != (Object)null)
			{
				Gui.SetForceHidden(true);
			}
		}
	}
	public enum HitVerdict
	{
		Allow,
		Cancel
	}
	public delegate HitVerdict HitFilter(Health health, DamageInfo info, bool hitFriendly);
	public static class KitHealth
	{
		private static readonly Dictionary<int, HitFilter> s_filters = new Dictionary<int, HitFilter>();

		internal static bool HasFilters => s_filters.Count > 0;

		public static void SetFilter(Health health, HitFilter filter)
		{
			if (!((Object)(object)health == (Object)null))
			{
				if (filter == null)
				{
					ClearFilter(health);
				}
				else
				{
					s_filters[((Object)health).GetInstanceID()] = filter;
				}
			}
		}

		public static void ClearFilter(Health health)
		{
			if ((Object)(object)health != (Object)null)
			{
				s_filters.Remove(((Object)health).GetInstanceID());
			}
		}

		internal static HitFilter FilterOf(Health health)
		{
			if (!((Object)(object)health != (Object)null) || !s_filters.TryGetValue(((Object)health).GetInstanceID(), out var value))
			{
				return null;
			}
			return value;
		}

		public static bool IsHeroHit(DamageInfo info)
		{
			if (info == null || info.m_source == null || (Object)(object)info.m_source.m_sourceOwnerPlayer == (Object)null)
			{
				return false;
			}
			PlayerData heroPlayerData = SystemLevel.GetHeroPlayerData();
			if (heroPlayerData != null && (Object)(object)heroPlayerData.GameObject != (Object)null)
			{
				return (Object)(object)heroPlayerData.GameObject == (Object)(object)info.m_source.m_sourceOwnerPlayer;
			}
			return false;
		}

		public static Health AddHealth(GameObject inactiveGo, float max, eAllowedDamageSource allowed, bool flashOnHit = true, float spawnInvulnerable = 0f)
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)inactiveGo == (Object)null)
			{
				throw new ArgumentNullException("inactiveGo");
			}
			if (inactiveGo.activeInHierarchy)
			{
				throw new InvalidOperationException("AddHealth needs an inactive object: Health.Awake copies m_healthMax at once");
			}
			Health val = inactiveGo.GetComponent<Health>();
			if ((Object)(object)val == (Object)null)
			{
				val = inactiveGo.AddComponent<Health>();
			}
			Util.Set(val, "m_healthMax", max);
			Util.Set(val, "m_allowedDamageSource", allowed);
			Util.Set(val, "m_flashOnHit", flashOnHit);
			Util.Set(val, "m_spawnInvulnerableTime", spawnInvulnerable);
			Util.Set(val, "m_damageResistance", 1f);
			Util.Set(val, "m_vulnerableState", string.Empty);
			return val;
		}
	}
	public sealed class Hittable : MonoBehaviour
	{
		private Action<Hittable, DamageInfo> m_onHit;

		private bool m_immortal;

		private float m_lastHit = -100f;

		public float MinGap;

		public Health Health { get; private set; }

		public BoxCollider Collider { get; private set; }

		public bool FlashOnHit
		{
			get
			{
				if ((Object)(object)Health != (Object)null)
				{
					return Util.Get<bool>(Health, "m_flashOnHit");
				}
				return false;
			}
			set
			{
				if ((Object)(object)Health != (Object)null)
				{
					Util.Set(Health, "m_flashOnHit", value);
				}
			}
		}

		public static Hittable Create(Transform parent, string name, Vector3 world, Vector2 size, eAllowedDamageSource allowed, Action<Hittable, DamageInfo> onHit, bool immortal = true, int layer = 25, float mortalMax = 1f)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_0032: 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_0043: 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_0062: 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_00a2: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name);
			val.SetActive(false);
			val.layer = layer;
			if ((Object)(object)parent != (Object)null)
			{
				val.transform.SetParent(parent, false);
			}
			val.transform.position = new Vector3(world.x, world.y, 0f);
			BoxCollider val2 = val.AddComponent<BoxCollider>();
			((Collider)val2).isTrigger = false;
			val2.size = new Vector3(size.x, size.y, 50f);
			Rigidbody obj = val.AddComponent<Rigidbody>();
			obj.isKinematic = true;
			obj.useGravity = false;
			Health health = KitHealth.AddHealth(val, immortal ? 10000f : Mathf.Max(0.01f, mortalMax), allowed);
			Hittable hittable = val.AddComponent<Hittable>();
			hittable.m_onHit = onHit;
			hittable.m_immortal = immortal;
			hittable.Health = health;
			hittable.Collider = val2;
			val.SetActive(true);
			return hittable;
		}

		public void SetActive(bool on)
		{
			((Component)this).gameObject.SetActive(on);
		}

		private void OnDamaged(DamageInfo info)
		{
			Count(info);
			if (m_immortal && (Object)(object)Health != (Object)null && Health.IsAlive())
			{
				Health.Heal(Health.GetHealthMax());
			}
		}

		private void OnKilled(DamageInfo info)
		{
			Count(info);
		}

		private void Count(DamageInfo info)
		{
			if (info == null || info.m_isDamageFromStatus || m_onHit == null || Time.time - m_lastHit < MinGap)
			{
				return;
			}
			m_lastHit = Time.time;
			try
			{
				m_onHit(this, info);
			}
			catch (Exception e)
			{
				Kit.Log.WarnOnce("hittable " + ((Object)this).name, e);
			}
		}
	}
	public abstract class KitBoss : Boss
	{
		private BossContext m_ctx;

		private Room m_room;

		private KitBody m_life;

		private BossBar m_bar;

		private int m_phase = 1;

		private bool m_spawned;

		private bool m_lifeWasSpawned;

		private bool m_introDone;

		private bool m_frozen;

		private bool m_killed;

		private bool m_arenaFailed;

		private bool m_inBuildArena;

		private bool m_noLife;

		private bool m_enterDone;

		private float m_introClock;

		private const float EnterTimeout = 3f;

		private readonly List<KitStation> m_stations = new List<KitStation>();

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

		private readonly List<int> m_kept = new List<int>();

		private float[] m_thresholds;

		private static readonly FieldInfo s_waitSeconds = typeof(WaitForSeconds).GetField("m_Seconds", BindingFlags.Instance | BindingFlags.NonPublic);

		protected virtual float[] PhaseThresholds => new float[2]
		{
			2f / 3f,
			1f / 3f
		};

		protected virtual Vector2 BarLocal => new Vector2(0f, 98f);

		protected virtual float IntroMinimum => 0.35f;

		public Room Arena => m_room;

		public BossContext Ctx => m_ctx;

		public KitBody LifeBody => m_life;

		public Health LifeHealth
		{
			get
			{
				if (!((Object)(object)m_life != (Object)null))
				{
					return null;
				}
				return m_life.Health;
			}
		}

		public BossBar Bar => m_bar;

		public int Phase => m_phase;

		public bool Fighting
		{
			get
			{
				if (m_introDone && !m_frozen && !base.m_won)
				{
					return !m_killed;
				}
				return false;
			}
		}

		public bool Frozen => m_frozen;

		public bool Killed => m_killed;

		public bool Won => base.m_won;

		public bool ArenaFailed => m_arenaFailed;

		public IList<KitStation> Stations => m_stations.AsReadOnly();

		public float UnpausedTime { get; private set; }

		public float PromptCeilingWorld
		{
			get
			{
				//IL_004b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0034: Unknown result type (might be due to invalid IL or missing references)
				//IL_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)
				if ((Object)(object)m_bar != (Object)null)
				{
					return m_bar.BottomWorld - 6f;
				}
				float num = (((Object)(object)m_room != (Object)null) ? ((Component)m_room).transform.position.y : ((Component)this).transform.position.y);
				float yMax;
				if (!((Object)(object)m_room != (Object)null))
				{
					Rect cameraBounds = KitArena.CameraBounds;
					yMax = ((Rect)(ref cameraBounds)).yMax;
				}
				else
				{
					yMax = ((Rect)(ref m_room.m_cameraBounds)).yMax;
				}
				return num + yMax - 8f;
			}
		}

		public event Action<int> PhaseChanged;

		public static void Configure(KitBoss b)
		{
			if ((Object)(object)b == (Object)null)
			{
				throw new ArgumentNullException("b");
			}
			BossContext bossContext = Kit.ContextOf(((object)b).GetType());
			if (bossContext == null)
			{
				throw new InvalidOperationException(((object)b).GetType().Name + " is not a registered boss type");
			}
			Configure(b, bossContext);
		}

		internal static void Configure(KitBoss b, BossContext ctx)
		{
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)ctx.ArenaTemplate == (Object)null)
			{
				throw new InvalidOperationException(ctx.Info.TemplateName + " has no arena template");
			}
			b.m_ctx = ctx;
			Util.Set(b, "m_displayName", ctx.Info.DisplayName);
			Util.Set(b, "m_bossUnleashedSceneName", "SceneMenuLose");
			Util.Set(b, "m_bossRoom", ctx.ArenaTemplate);
			Util.Set(b, "m_entryRoom", HydraConfig.EntryRoom);
			Util.Set(b, "m_bossPosition", ctx.BossPositionLocal);
			Util.Set(b, "m_entryRoomProps", HydraConfig.EntryRoomProps);
			Util.Set(b, "m_bossRoomProps", null);
			Util.Set(b, "m_playerEntryRoomOffset", HydraConfig.PlayerEntryRoomOffset);
			Util.Set(b, "m_heroWinPauseTime", 4.3f);
			Util.Set(b, "m_heroWinRunAroundTime", 6.25f);
			Util.Set(b, "m_roomDoorSealPrefab", HydraConfig.DoorSeal);
			Util.Set(b, "m_minPlayersRequired", 0);
			Util.Set(b, "m_heroWinEffect", HydraConfig.HeroWinEffect);
			Util.Set(b, "m_heroWinEffectDelay", HydraConfig.HeroWinEffectDelay);
			Util.Set(b, "m_bossWinEffect", HydraConfig.BossWinEffect);
			Util.Set(b, "m_bossWinEffectDelay", HydraConfig.BossWinEffectDelay);
			Util.Set(b, "m_musicBossOverride", null);
		}

		internal float[] ThresholdsSorted()
		{
			if (m_thresholds != null)
			{
				return m_thresholds;
			}
			float[] source = PhaseThresholds ?? new float[0];
			m_thresholds = (from x in source.Where((float x) => x > 0f && x < 1f).Distinct()
				orderby x descending
				select x).ToArray();
			return m_thresholds;
		}

		internal static float SmallestGap(float[] sortedDesc)
		{
			float num = 1f;
			float num2 = 1f;
			foreach (float num3 in sortedDesc)
			{
				num = Mathf.Min(num, num2 - num3);
				num2 = num3;
			}
			return Mathf.Min(num, num2);
		}

		protected abstract void BuildArena(Room room);

		protected abstract KitBody SpawnBodies(Room room);

		protected virtual IEnumerator Intro()
		{
			yield return WaitGameTime(2f);
		}

		protected virtual void OnFightStart()
		{
		}

		protected virtual void OnPhase(int phase)
		{
		}

		protected virtual void OnBossDying(DamageInfo info)
		{
		}

		protected virtual void OnHeroKilledKit(Player hero)
		{
		}

		protected virtual void OnFrozen(bool frozen)
		{
		}

		protected virtual void KitUpdate()
		{
		}

		protected virtual void KitLateUpdate()
		{
		}

		protected virtual void KitFixedUpdate()
		{
		}

		protected virtual void OnCleanup()
		{
		}

		private void Awake()
		{
			try
			{
				BossContext bossContext = (m_ctx = Kit.ContextOf(((object)this).GetType()));
				if (bossContext != null && (Object)(object)bossContext.ArenaTemplate != (Object)null)
				{
					Configure(this, bossContext);
				}
			}
			catch (Exception e)
			{
				Kit.Log.WarnOnce("boss configure " + ((object)this).GetType().Name, e);
			}
		}

		private void Start()
		{
			if ((Object)(object)((Component)this).transform.parent == (Object)null || m_ctx == null || !m_ctx.Ready)
			{
				return;
			}
			m_room = ((Component)((Component)this).transform.parent).GetComponent<Room>();
			if ((Object)(object)m_room == (Object)null)
			{
				m_ctx.Log.Warn("The boss controller is not under a room");
				return;
			}
			KitRoom.RegisterArena(m_room);
			m_ctx.ApplyBossDamage();
			m_inBuildArena = true;
			try
			{
				BuildArena(m_room);
				m_ctx.Log.Info("Arena built (" + m_stations.Count + " stations)");
				KitSelfTest.Note("arena built");
			}
			catch (Exception ex)
			{
				m_arenaFailed = true;
				m_ctx.Log.Error("Arena build failed: " + ex);
				KitSelfTest.Note("arena build failed: " + ex.Message);
			}
			finally
			{
				m_inBuildArena = false;
			}
			KitRoom.MarkPathfinderDirty(m_room);
		}

		private void Update()
		{
			UnpausedTime += Time.deltaTime;
			if ((Object)(object)m_room == (Object)null || !m_spawned)
			{
				return;
			}
			if (!m_introDone)
			{
				m_introClock += Time.deltaTime;
			}
			try
			{
				if ((Object)(object)m_bar != (Object)null && Fighting && (Object)(object)m_life != (Object)null && m_life.Alive)
				{
					m_bar.KeepLit();
				}
				if (!m_killed && m_lifeWasSpawned)
				{
					if ((Object)(object)m_life == (Object)null)
					{
						m_ctx.Log.Error("The life body was removed without dying; the boss counts as killed so the run can go on");
						Win();
					}
					else if ((Object)(object)m_life.Health != (Object)null && !m_life.Health.IsAlive())
					{
						Win();
					}
					else
					{
						CheckPhase();
					}
				}
			}
			catch (Exception e)
			{
				Kit.Log.WarnOnce("boss update " + ((object)this).GetType().Name, e);
			}
			try
			{
				KitUpdate();
			}
			catch (Exception e2)
			{
				Kit.Log.WarnOnce("boss KitUpdate " + ((object)this).GetType().Name, e2);
			}
		}

		private void FixedUpdate()
		{
			if ((Object)(object)m_room == (Object)null || !m_spawned)
			{
				return;
			}
			try
			{
				KitFixedUpdate();
			}
			catch (Exception e)
			{
				Kit.Log.WarnOnce("boss KitFixedUpdate " + ((object)this).GetType().Name, e);
			}
		}

		private void LateUpdate()
		{
			if ((Object)(object)m_room == (Object)null)
			{
				return;
			}
			try
			{
				KitLateUpdate();
			}
			catch (Exception e)
			{
				Kit.Log.WarnOnce("boss KitLateUpdate " + ((object)this).GetType().Name, e);
			}
		}

		private void OnDestroy()
		{
			try
			{
				if ((Object)(object)m_room != (Object)null)
				{
					KitRoom.UnregisterArena(m_room);
				}
				foreach (KitStation station in m_stations)
				{
					if ((Object)(object)station != (Object)null)
					{
						KitStations.Unregister(station);
					}
				}
				foreach (GameObject root in m_roots)
				{
					if ((Object)(object)root == (Object)null)
					{
						continue;
					}
					try
					{
						KitBody component = root.GetComponent<KitBody>();
						if ((Object)(object)component == (Object)null || component.Alive)
						{
							ExtentionsMethodsPool.Despawn(root);
						}
					}
					catch (Exception e)
					{
						Kit.Log.WarnOnce("despawn root " + ((Object)root).name, e);
					}
				}
				m_roots.Clear();
				foreach (int item in m_kept)
				{
					if (KitBodies.KeptInRoom.TryGetValue(item, out var value) && ((Object)(object)value == (Object)(object)this || (Object)(object)value == (Object)null))
					{
						KitBodies.KeptInRoom.Remove(item);
					}
				}
				m_kept.Clear();
			}
			catch (Exception e2)
			{
				Kit.Log.WarnOnce("boss destroy", e2);
			}
			try
			{
				OnCleanup();
			}
			catch (Exception e3)
			{
				Kit.Log.WarnOnce("boss OnCleanup " + ((object)this).GetType().Name, e3);
			}
		}

		public sealed override void OnEnterBossRoom()
		{
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			if (SystemLevel.GetHeroPlayerData() == null || (Object)(object)SystemLevel.GetHeroObject() == (Object)null || (Object)(object)m_room == (Object)null)
			{
				return;
			}
			((Boss)this).OnEnterBossRoom();
			if (!m_spawned)
			{
				m_spawned = true;
				try
				{
					m_life = SpawnBodies(m_room);
				}
				catch (Exception ex)
				{
					m_life = null;
					m_ctx.Log.Error("SpawnBodies failed: " + ex);
				}
				if ((Object)(object)m_life != (Object)null)
				{
					m_life.IsLife = true;
					m_lifeWasSpawned = true;
					m_life.Damaged += OnLifeDamaged;
					m_life.Died += OnLifeDied;
					CheckLifeCap();
					m_bar = BossBar.Spawn(this, m_life.Health, BarLocal);
				}
				else
				{
					m_noLife = true;
					m_ctx.Log.Error("No life body: the fight is forfeited after the intro so the run can go on");
				}
				((MonoBehaviour)this).StartCoroutine(IntroRunner());
				return;
			}
			m_frozen = false;
			try
			{
				OnFrozen(frozen: false);
			}
			catch (Exception e)
			{
				Kit.Log.WarnOnce("boss OnFrozen", e);
			}
		}

		public sealed override void OnExitBossRoom()
		{
			try
			{
				((Boss)this).OnExitBossRoom();
				m_frozen = true;
				OnFrozen(frozen: true);
			}
			catch (Exception e)
			{
				Kit.Log.WarnOnce("boss exit room", e);
			}
		}

		public sealed override void OnHeroKilled(Player killed, DamageInfo damage)
		{
			((Boss)this).OnHeroKilled(killed, damage);
			try
			{
				((Boss)this).StopKillingBlowEffects(killed, damage);
			}
			catch (Exception e)
			{
				Kit.Log.WarnOnce("stop killing blow", e);
			}
			try
			{
				if ((Object)(object)m_life != (Object)null && m_life.Alive)
				{
					m_life.Health.StartInvincibility("WON");
				}
				SetStationsSuspended(suspended: true);
				OnHeroKilledKit(killed);
			}
			catch (Exception e2)
			{
				Kit.Log.WarnOnce("boss hero killed", e2);
			}
			KitSelfTest.Note("hero killed");
		}

		private IEnumerator EnterSequenceTracked()
		{
			yield return ((MonoBehaviour)this).StartCoroutine(((Boss)this).CoroutineHeroEnterSequence());
			m_enterDone = true;
		}

		public static IEnumerator WaitGameTime(float seconds)
		{
			float left = seconds;
			while (left > 0f)
			{
				yield return null;
				if (!SystemTime.Paused)
				{
					left -= Time.deltaTime;
				}
			}
		}

		private static bool TryReadSeconds(WaitForSeconds w, out float seconds)
		{
			seconds = 0f;
			if (w == null || (object)s_waitSeconds == null)
			{
				return false;
			}
			try
			{
				seconds = (float)s_waitSeconds.GetValue(w);
				return true;
			}
			catch (Exception)
			{
				return false;
			}
		}

		private IEnumerator IntroRunner()
		{
			m_introClock = 0f;
			m_enterDone = false;
			((MonoBehaviour)this).StartCoroutine(EnterSequenceTracked());
			Stack<IEnumerator> stack = new Stack<IEnumerator>();
			try
			{
				IEnumerator enumerator = (m_noLife ? null : Intro());
				if (enumerator != null)
				{
					stack.Push(enumerator);
				}
			}
			catch (Exception ex)
			{
				m_ctx.Log.Error("Intro failed: " + ex);
			}
			while (stack.Count > 0)
			{
				if (SystemTime.Paused)
				{
					yield return null;
					continue;
				}
				object current;
				try
				{
					IEnumerator enumerator2 = stack.Peek();
					if (!enumerator2.MoveNext())
					{
						stack.Pop();
						continue;
					}
					current = enumerator2.Current;
				}
				catch (Exception ex2)
				{
					m_ctx.Log.Error("Intro failed, the fight starts now: " + ex2);
					stack.Clear();
					break;
				}
				if (current is IEnumerator item)
				{
					stack.Push(item);
					continue;
				}
				WaitForSeconds val = (WaitForSeconds)((current is WaitForSeconds) ? current : null);
				if (val != null && TryReadSeconds(val, out var seconds))
				{
					stack.Push(WaitGameTime(seconds));
				}
				else
				{
					yield return current;
				}
			}
			while (m_introClock < IntroMinimum || (!m_enterDone && m_introClock < IntroMinimum + 3f))
			{
				yield return null;
			}
			if (!m_enterDone)
			{
				m_ctx.Log.Warn("The game's hero enter sequence did not finish within " + 3f + " s of unpaused time; the fight starts anyway");
			}
			try
			{
				((Boss)this).OnSpawnComplete();
			}
			catch (Exception ex3)
			{
				m_ctx.Log.Error("OnSpawnComplete failed: " + ex3);
			}
			m_introDone = true;
			if (m_noLife)
			{
				Win();
				yield break;
			}
			if (!base.m_won && !m_killed)
			{
				try
				{
					if ((Object)(object)m_bar != (Object)null && (Object)(object)m_bar.Gui != (Object)null)
					{
						m_bar.Gui.Show(false);
					}
					else if ((Object)(object)m_life != (Object)null && (Object)(object)m_life.Player != (Object)null && (Object)(object)m_life.Player.GetGUIHealthBar() != (Object)null)
					{
						m_life.Player.GetGUIHealthBar().Show(false);
					}
				}
				catch (Exception e)
				{
					Kit.Log.WarnOnce("bar show", e);
				}
				try
				{
					OnFightStart();
				}
				catch (Exception ex4)
				{
					m_ctx.Log.Error("OnFightStart failed: " + ex4);
				}
			}
			KitSelfTest.Note("fight started");
		}

		private void OnLifeDamaged(DamageInfo info)
		{
			CheckPhase();
		}

		private void OnLifeDied(DamageInfo info)
		{
			Win(info);
		}

		private void CheckPhase()
		{
			if (m_killed || (Object)(object)m_life == (Object)null || (Object)(object)m_life.Health == (Object)null || !m_life.Health.IsAlive())
			{
				return;
			}
			float healthRatio = m_life.Health.GetHealthRatio();
			float[] array = ThresholdsSorted();
			int num = 1;
			float[] array2 = array;
			foreach (float num2 in array2)
			{
				if (healthRatio <= num2)
				{
					num++;
				}
			}
			while (m_phase < num && !m_killed)
			{
				m_phase++;
				foreach (KitStation station in m_stations)
				{
					if ((Object)(object)station == (Object)null)
					{
						continue;
					}
					try
					{
						if (station.Spec.RetirePhase > 0 && station.Spec.RetirePhase <= m_phase)
						{
							station.Retire();
						}
						else if (station.Dormant && !station.Spec.WakeByBoss && station.Spec.WakePhase == m_phase && (!station.IsFollower || station.Group == null || !station.Group.Seat.Dormant))
						{
							station.SetDormant(dormant: false);
						}
					}
					catch (Exception e)
					{
						Kit.Log.WarnOnce("phase stations", e);
					}
				}
				KitRoom.MarkPathfinderDirty(m_room);
				KitSelfTest.Note("phase " + m_phase);
				try
				{
					OnPhase(m_phase);
				}
				catch (Exception ex)
				{
					m_ctx.Log.Error("OnPhase(" + m_phase + ") failed: " + ex);
				}
				Action<int> action = this.PhaseChanged;
				if (action != null)
				{
					try
					{
						action(m_phase);
					}
					catch (Exception e2)
					{
						Kit.Log.WarnOnce("PhaseChanged", e2);
					}
				}
			}
		}

		private void CheckLifeCap()
		{
			try
			{
				float[] array = ThresholdsSorted();
				if (array.Length != 0 && m_life.Spec != null)
				{
					float num = SmallestGap(array) * m_life.Spec.HealthMax;
					if (m_life.Spec.MaxDamagePerHit <= 0f || m_life.Spec.MaxDamagePerHit >= num)
					{
						m_ctx.Log.Error("The life body's MaxDamagePerHit (" + m_life.Spec.MaxDamagePerHit + ") is not below the smallest phase gap (" + num + "): one hit can skip a phase");
					}
				}
			}
			catch (Exception e)
			{
				Kit.Log.WarnOnce("life cap check", e);
			}
		}

		public void Win(DamageInfo info = null)
		{
			if (m_killed)
			{
				return;
			}
			m_killed = true;
			try
			{
				foreach (KitStation station in m_stations)
				{
					if ((Object)(object)station != (Object)null)
					{
						station.ShutDown();
					}
				}
				OnBossDying(info);
			}
			catch (Exception e)
			{
				Kit.Log.WarnOnce("boss dying " + ((object)this).GetType().Name, e);
			}
			finally
			{
				Singleton<SystemLevel>.Get.OnBossKilled();
			}
			KitSelfTest.Note("boss killed");
		}

		public KitStation SpawnStation(GameObject template, Vector2 roomLocal, StationSpec spec)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			if (!m_inBuildArena)
			{
				throw new InvalidOperationException("SpawnStation is only valid inside BuildArena (bot caches)");
			}
			if ((Object)(object)template == (Object)null)
			{
				throw new ArgumentNullException("template");
			}
			GameObject val = m_room.SpawnInRoom(template, World(roomLocal));
			if ((Object)(object)val == (Object)null)
			{
				throw new InvalidOperationException("spawning station " + ((Object)template).name + " failed");
			}
			KitRoom.MatchHidden(m_room, val);
			KitStation kitStation = val.AddComponent<KitStation>();
			kitStation.Init(this, spec ?? new StationSpec());
			m_stations.Add(kitStation);
			if (kitStation.Spec.WakePhase > 1)
			{
				kitStation.SetDormant(dormant: true);
			}
			return kitStation;
		}

		public StationGroup CreateGroup(KitStation seat, IList<KitStation> followers, GroupMode mode)
		{
			return new StationGroup(this, seat, followers, mode);
		}

		public void SetStationsSuspended(bool suspended)
		{
			if (!suspended && base.m_won)
			{
				Kit.Log.Info("stations stay suspended: the hero is dead (end of a beat after the hero died)");
				return;
			}
			foreach (KitStation station in m_stations)
			{
				if ((Object)(object)station != (Object)null)
				{
					station.SetArenaSuspended(suspended);
				}
			}
		}

		public void WakeStations(int phase)
		{
			for (int i = 0; i < 2; i++)
			{
				bool flag = i == 1;
				foreach (KitStation station in m_stations)
				{
					if ((Object)(object)station == (Object)null || station.IsFollower != flag)
					{
						continue;
					}
					try
					{
						if (station.Dormant && !station.Retired && station.Spec.WakePhase <= phase && (!station.IsFollower || station.Group == null || !station.Group.Seat.Dormant))
						{
							station.SetDormant(dormant: false);
						}
					}
					catch (Exception e)
					{
						Kit.Log.WarnOnce("wake stations", e);
					}
				}
			}
			KitRoom.MarkPathfinderDirty(m_room);
		}

		public void KeepInRoom(Player player, bool keep = true)
		{
			if ((Object)(object)player == (Object)null)
			{
				return;
			}
			int instanceID = ((Object)player).GetInstanceID();
			if (keep)
			{
				KitBodies.KeptInRoom[instanceID] = this;
				if (!m_kept.Contains(instanceID))
				{
					m_kept.Add(instanceID);
				}
			}
			else
			{
				if (KitBodies.KeptInRoom.TryGetValue(instanceID, out var value) && ((Object)(object)value == (Object)(object)this || (Object)(object)value == (Object)null))
				{
					KitBodies.KeptInRoom.Remove(instanceID);
				}
				m_kept.Remove(instanceID);
			}
		}

		public void TrackRoot(GameObject go)
		{
			if ((Object)(object)go != (Object)null && !m_roots.Contains(go))
			{
				m_roots.Add(go);
			}
		}

		public Vector2 RoomLocal(Vector3 world)
		{
			//IL_002b: 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_000e: 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_001f: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)m_room != (Object)null))
			{
				return Vector2.op_Implicit(world - ((Component)this).transform.position);
			}
			return KitRoom.Local(m_room, world);
		}

		public Vector3 World(Vector2 roomLocal)
		{
			//IL_0021: Unknown result type (might be due to inval

plugins/CrawlCustomBosses/LabyrinthBoss.dll

Decompiled 4 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("LabyrinthBoss")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("LabyrinthBoss")]
[assembly: AssemblyTitle("LabyrinthBoss")]
[assembly: AssemblyVersion("1.0.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 LabyrinthBoss
{
	internal static class Art
	{
		public class Sheet
		{
			private readonly string m_name;

			private readonly List<Texture2D> m_frames = new List<Texture2D>();

			private readonly Dictionary<string, int[]> m_strips = new Dictionary<string, int[]>();

			public exAtlas Atlas { get; private set; }

			public Sheet(string name)
			{
				m_name = name;
			}

			public void AddStrip(string key, string resource, int frames)
			{
				List<Texture2D> collection = Slice(LoadPng(resource), frames);
				int count = m_frames.Count;
				m_frames.AddRange(collection);
				m_strips[key] = Enumerable.Range(count, frames).ToArray();
			}

			public void AddGrid(string key, string resource, int cols, int rows)
			{
				//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
				//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d5: Expected O, but got Unknown
				Texture2D val = LoadPng(resource);
				if (((Texture)val).width % cols != 0 || ((Texture)val).height % rows != 0)
				{
					throw new FormatException(resource + " (" + ((Texture)val).width + "x" + ((Texture)val).height + ") does not divide into " + cols + "x" + rows + " tiles");
				}
				int num = ((Texture)val).width / cols;
				int num2 = ((Texture)val).height / rows;
				int count = m_frames.Count;
				for (int i = 0; i < rows; i++)
				{
					for (int j = 0; j < cols; j++)
					{
						Texture2D val2 = new Texture2D(num, num2, (TextureFormat)5, false)
						{
							filterMode = (FilterMode)0,
							wrapMode = (TextureWrapMode)1
						};
						val2.SetPixels(val.GetPixels(j * num, ((Texture)val).height - (i + 1) * num2, num, num2));
						val2.Apply();
						m_frames.Add(val2);
					}
				}
				m_strips[key] = Enumerable.Range(count, cols * rows).ToArray();
			}

			public int[] Frames(string key)
			{
				if (!m_strips.TryGetValue(key, out var value))
				{
					throw new KeyNotFoundException("no strip " + key + " in sheet " + m_name);
				}
				return value;
			}

			public void Build(Material baseMaterial)
			{
				//IL_0004: Unknown result type (might be due to invalid IL or missing references)
				//IL_000a: Expected O, but got Unknown
				//IL_0121: Unknown result type (might be due to invalid IL or missing references)
				//IL_0126: Unknown result type (might be due to invalid IL or missing references)
				//IL_013c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0143: Unknown result type (might be due to invalid IL or missing references)
				//IL_014c: Expected O, but got Unknown
				//IL_019a: Unknown result type (might be due to invalid IL or missing references)
				//IL_019f: Unknown result type (might be due to invalid IL or missing references)
				//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
				//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
				//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
				//IL_021d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0222: 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_022b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0230: Unknown result type (might be due to invalid IL or missing references)
				//IL_0235: Unknown result type (might be due to invalid IL or missing references)
				//IL_023d: Expected O, but got Unknown
				Texture2D val = new Texture2D(1, 1, (TextureFormat)5, false);
				Rect[] array = val.PackTextures(m_frames.ToArray(), 2, 4096, false);
				if (array == null || array.Length != m_frames.Count)
				{
					throw new InvalidOperationException("PackTextures failed for " + m_name);
				}
				((Texture)val).filterMode = (FilterMode)0;
				((Texture)val).wrapMode = (TextureWrapMode)1;
				((Object)val).name = m_name + "_tex";
				((Object)val).hideFlags = (HideFlags)32;
				for (int i = 0; i < array.Length; i++)
				{
					float num = ((Rect)(ref array[i])).width * (float)((Texture)val).width;
					float num2 = ((Rect)(ref array[i])).height * (float)((Texture)val).height;
					if (Mathf.Abs(num - (float)((Texture)m_frames[i]).width) > 0.5f || Mathf.Abs(num2 - (float)((Texture)m_frames[i]).height) > 0.5f)
					{
						throw new InvalidOperationException(m_name + ": frame " + i + " was resized by the packer");
					}
				}
				Material material = new Material(baseMaterial)
				{
					name = m_name + "_mat",
					mainTexture = (Texture)(object)val,
					hideFlags = (HideFlags)32
				};
				exAtlas val2 = ScriptableObject.CreateInstance<exAtlas>();
				((Object)val2).name = m_name;
				((Object)val2).hideFlags = (HideFlags)32;
				val2.texture = val;
				val2.material = material;
				val2.elements = (Element[])(object)new Element[m_frames.Count];
				for (int j = 0; j < m_frames.Count; j++)
				{
					val2.elements[j] = new Element
					{
						name = m_name + "_" + j,
						originalWidth = ((Texture)m_frames[j]).width,
						originalHeight = ((Texture)m_frames[j]).height,
						trimRect = new Rect(0f, 0f, (float)((Texture)m_frames[j]).width, (float)((Texture)m_frames[j]).height),
						coords = array[j],
						rotated = false
					};
				}
				Atlas = val2;
			}

			public exSpriteAnimClip Clip(string name, string key, float fps, WrapMode wrap, IEnumerable<EventInfo> events = null, int[] order = null)
			{
				//IL_0059: 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_0062: Unknown result type (might be due to invalid IL or missing references)
				int[] frames = Frames(key);
				if (order != null)
				{
					frames = order.Select((int i) => frames[i]).ToArray();
				}
				exSpriteAnimClip val = ScriptableObject.CreateInstance<exSpriteAnimClip>();
				((Object)val).name = name;
				((Object)val).hideFlags = (HideFlags)32;
				val.wrapMode = wrap;
				val.stopAction = (StopAction)0;
				val.speed = 1f;
				val.sampleRate = 60f;
				float num = (val.length = (float)frames.Length / fps);
				val.frameInfos = ((IEnumerable<int>)frames).Select((Func<int, FrameInfo>)((int i) => new FrameInfo
				{
					atlas = Atlas,
					index = i,
					length = 1f / fps
				})).ToList();
				val.eventInfos = (events ?? Enumerable.Empty<EventInfo>()).OrderBy((EventInfo e) => e.time).ToList();
				foreach (EventInfo eventInfo in val.eventInfos)
				{
					if (eventInfo.time < 0f || eventInfo.time > num)
					{
						throw new ArgumentOutOfRangeException(name + ": event " + eventInfo.methodName + " at " + eventInfo.time + " is outside the clip (" + num + " s)");
					}
				}
				return val;
			}
		}

		private class RefEq : IEqualityComparer<object>
		{
			public new bool Equals(object a, object b)
			{
				return a == b;
			}

			public int GetHashCode(object o)
			{
				return RuntimeHelpers.GetHashCode(o);
			}
		}

		public static Texture2D LoadPng(string resource)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Expected O, but got Unknown
			Texture2D val = new Texture2D(2, 2, (TextureFormat)5, false);
			if (!val.LoadImage(Util.Resource(resource)))
			{
				throw new FormatException("could not decode " + resource);
			}
			((Texture)val).filterMode = (FilterMode)0;
			((Texture)val).wrapMode = (TextureWrapMode)1;
			((Object)val).name = resource;
			((Object)val).hideFlags = (HideFlags)32;
			return val;
		}

		public static List<Texture2D> Slice(Texture2D strip, int frames)
		{
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Expected O, but got Unknown
			if (frames < 1 || ((Texture)strip).width % frames != 0)
			{
				throw new FormatException(((Object)strip).name + " is " + ((Texture)strip).width + " px wide, which does not divide into " + frames + " frames");
			}
			int num = ((Texture)strip).width / frames;
			List<Texture2D> list = new List<Texture2D>(frames);
			for (int i = 0; i < frames; i++)
			{
				Texture2D val = new Texture2D(num, ((Texture)strip).height, (TextureFormat)5, false)
				{
					filterMode = (FilterMode)0,
					wrapMode = (TextureWrapMode)1
				};
				val.SetPixels(strip.GetPixels(i * num, 0, num, ((Texture)strip).height));
				val.Apply();
				list.Add(val);
			}
			return list;
		}

		public static EventInfo Event(float time, string method)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: 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_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_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			return new EventInfo
			{
				time = time,
				methodName = method,
				paramType = (ParamType)0,
				msgOptions = (SendMessageOptions)1
			};
		}

		public static EventInfo Event(float time, string method, int value)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			EventInfo obj = Event(time, method);
			obj.paramType = (ParamType)3;
			obj.intParam = value;
			return obj;
		}

		public static EventInfo Event(float time, string method, float value)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			EventInfo obj = Event(time, method);
			obj.paramType = (ParamType)2;
			obj.floatParam = value;
			return obj;
		}

		public static EventInfo Sound(float time, AudioCue cue)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			EventInfo obj = Event(time, "AnimSound");
			obj.paramType = (ParamType)5;
			obj.objectParam = (Object)(object)(((Object)(object)cue != (Object)null) ? ((Component)cue).gameObject : null);
			return obj;
		}

		public static int SwapClips(GameObject root, Func<exSpriteAnimClip, exSpriteAnimClip> map)
		{
			int num = 0;
			HashSet<object> seen = new HashSet<object>(new RefEq());
			Component[] componentsInChildren = root.GetComponentsInChildren<Component>(true);
			foreach (Component val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null) && !(val is Transform))
				{
					num += Walk(val, map, seen, 0);
				}
			}
			return num;
		}

		private static int Walk(object o, Func<exSpriteAnimClip, exSpriteAnimClip> map, HashSet<object> seen, int depth)
		{
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Expected O, but got Unknown
			if (o == null || depth > 7 || !seen.Add(o))
			{
				return 0;
			}
			int num = 0;
			Type type = o.GetType();
			while ((object)type != null && (object)type != typeof(MonoBehaviour) && (object)type != typeof(Component) && (object)type != typeof(object))
			{
				FieldInfo[] fields = type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (FieldInfo fieldInfo in fields)
				{
					if (fieldInfo.IsStatic || fieldInfo.IsLiteral)
					{
						continue;
					}
					Type fieldType = fieldInfo.FieldType;
					if ((object)fieldType == typeof(exSpriteAnimClip))
					{
						object? value = fieldInfo.GetValue(o);
						exSpriteAnimClip val = (exSpriteAnimClip)((value is exSpriteAnimClip) ? value : null);
						if ((Object)(object)val != (Object)null)
						{
							exSpriteAnimClip val2 = map(val);
							if ((Object)(object)val2 != (Object)null && (Object)(object)val2 != (Object)(object)val)
							{
								fieldInfo.SetValue(o, val2);
								num++;
							}
						}
					}
					else if (typeof(IList).IsAssignableFrom(fieldType))
					{
						if (!(fieldInfo.GetValue(o) is IList list))
						{
							continue;
						}
						for (int j = 0; j < list.Count; j++)
						{
							object obj = list[j];
							if (obj is exSpriteAnimClip)
							{
								exSpriteAnimClip val3 = map((exSpriteAnimClip)obj);
								if ((Object)(object)val3 != (Object)null && val3 != obj)
								{
									list[j] = val3;
									num++;
								}
							}
							else if (obj != null && IsWalkable(obj.GetType()))
							{
								num += Walk(obj, map, seen, depth + 1);
							}
						}
					}
					else if (IsWalkable(fieldType))
					{
						num += Walk(fieldInfo.GetValue(o), map, seen, depth + 1);
					}
				}
				type = type.BaseType;
			}
			return num;
		}

		private static bool IsWalkable(Type t)
		{
			if (t.IsClass && !typeof(Object).IsAssignableFrom(t) && (object)t != typeof(string))
			{
				return t.IsDefined(typeof(SerializableAttribute), inherit: false);
			}
			return false;
		}
	}
	public class AsterionBrain : PlayerAI
	{
		private static readonly FieldRef<PlayerAI, Vector2> s_face = AccessTools.FieldRefAccess<PlayerAI, Vector2>("m_faceDirection");

		private static readonly FieldRef<PlayerAI, float> s_move = AccessTools.FieldRefAccess<PlayerAI, float>("m_moveRatio");

		internal int RequestedAttack = -1;

		public void SetMove(Vector2 dir, float ratio)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			if (((Vector2)(ref dir)).sqrMagnitude > 0.0001f)
			{
				s_face.Invoke((PlayerAI)(object)this) = ((Vector2)(ref dir)).normalized;
			}
			s_move.Invoke((PlayerAI)(object)this) = Mathf.Clamp01(ratio);
		}

		public override int GetAttackToStart()
		{
			return RequestedAttack;
		}

		public override void OnAttack()
		{
			RequestedAttack = -1;
		}

		private void Update()
		{
		}
	}
	public class Asterion : MonoBehaviour
	{
		private LabyrinthBoss m_boss;

		private Maze m_maze;

		private Room m_room;

		private Player m_player;

		private PlayerMovement m_move;

		private Health m_health;

		private AsterionBrain m_brain;

		private exSpriteAnimation m_anim;

		private Rigidbody m_body;

		private GUIHealthBar m_bossBar;

		private float m_lastHurtSound = -10f;

		private const float HurtSoundGap = 0.25f;

		private bool m_fighting;

		private bool m_frozen;

		private bool m_busy;

		private bool m_dead;

		private bool m_vulnerable;

		private bool m_heroDead;

		internal bool AllowStun;

		private float m_nextCharge;

		private float m_nextCleave;

		private float m_nextSlam;

		private float m_nextPath;

		private Vector2 m_waypoint;

		private int m_phase = 1;

		private int m_pendingPhase;

		private bool m_hornCharge;

		private Vector2 m_hornDir;

		private static readonly FieldInfo s_barTimer = typeof(GUIHealthBar).GetField("m_showTimer", BindingFlags.Instance | BindingFlags.NonPublic);

		private float m_lastPath;

		private Vector2 m_lastGood;

		private float m_hornRequestTime;

		private bool m_hornQueuedBusy;

		private bool m_wasBusy;

		private float m_freeSince;

		private bool m_hornChargeUsed;

		internal bool Alive
		{
			get
			{
				if (!m_dead && (Object)(object)m_health != (Object)null)
				{
					return m_health.IsAlive();
				}
				return false;
			}
		}

		internal bool Vulnerable => m_vulnerable;

		internal float HornHeight => 48f;

		private GUIHealthBar ShownBar
		{
			get
			{
				if (!((Object)(object)m_bossBar != (Object)null))
				{
					return m_player.GetGUIHealthBar();
				}
				return m_bossBar;
			}
		}

		private bool HoldingPhaseFloor
		{
			get
			{
				if ((Object)(object)m_boss != (Object)null && m_boss.PhaseSettling && m_phase < 3)
				{
					return (Object)(object)m_health != (Object)null;
				}
				return false;
			}
		}

		private float PhaseFloor => m_health.GetHealthMax() * (float)(3 - m_phase) / 3f + 0.05f;

		internal void Setup(LabyrinthBoss boss, Maze maze, Room room)
		{
			m_boss = boss;
			m_maze = maze;
			m_room = room;
			m_player = ((Component)this).GetComponent<Player>();
			m_move = ((Component)this).GetComponent<PlayerMovement>();
			m_health = ((Component)this).GetComponent<Health>();
			m_brain = ((Component)this).GetComponent<AsterionBrain>();
			m_anim = ((Component)this).GetComponent<exSpriteAnimation>();
			m_body = ((Component)this).GetComponent<Rigidbody>();
			Patches.RegisterAsterion(this);
		}

		internal void AfterInit()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: 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_012e: 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_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			m_health.SetMaxDamagePerHit(6f);
			ValueModifierStack val = new ValueModifierStack();
			val.Add(new ValueModifier("BOSS", (eModifierType)2, SystemBalance.BossResistanceMultiplier, 128f));
			m_health.ModifyDamageResistance(val);
			m_player.CallbackOnDie = (Action<Player, DamageInfo>)Delegate.Combine(m_player.CallbackOnDie, new Action<Player, DamageInfo>(OnDie));
			try
			{
				Util.Set(m_player, "m_healthBarOffset", (object)new Vector3(0f, HornHeight + 26f, -20f));
				GUIHealthBar gUIHealthBar = m_player.GetGUIHealthBar();
				if ((Object)(object)gUIHealthBar != (Object)null)
				{
					gUIHealthBar.SetHealthComponent(m_health);
					((Component)gUIHealthBar).transform.position = ((Component)this).transform.position + new Vector3(0f, HornHeight + 26f, -20f);
				}
			}
			catch (Exception e)
			{
				Util.WarnOnce("health bar", e);
			}
			m_brain.SetMove(Vector2.right, 0f);
			m_frozen = true;
			m_lastGood = Local(((Component)this).transform.position);
		}

		internal void SetBossBar(GUIHealthBar bar)
		{
			m_bossBar = bar;
			GUIHealthBar gUIHealthBar = m_player.GetGUIHealthBar();
			if ((Object)(object)bar != (Object)null && (Object)(object)gUIHealthBar != (Object)null)
			{
				gUIHealthBar.SetForceHidden(true);
			}
		}

		internal void PlayIntroRoar()
		{
			if (Alive)
			{
				m_player.StartCutscene(Templates.Clips["Roar"], false, 0f);
				((MonoBehaviour)this).StartCoroutine(EndCutsceneAfter(Templates.Clips["Roar"].length));
			}
		}

		private IEnumerator EndCutsceneAfter(float t)
		{
			yield return (object)new WaitForSeconds(t);
			if (Alive && (int)m_player.GetState() == 13)
			{
				m_player.EndCutscene();
			}
		}

		internal void StartFight()
		{
			m_fighting = true;
			m_frozen = false;
			GUIHealthBar shownBar = ShownBar;
			if ((Object)(object)shownBar != (Object)null)
			{
				shownBar.Show(false);
			}
			float time = Time.time;
			m_nextCharge = time + 2.5f;
			m_nextCleave = time;
			m_nextSlam = time + 4f;
		}

		internal void SetFrozen(bool frozen)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			m_frozen = frozen;
			if (frozen)
			{
				m_brain.SetMove(Vector2.zero, 0f);
				m_brain.RequestedAttack = -1;
				m_hornCharge = false;
			}
		}

		internal void OnHeroKilled()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			m_heroDead = true;
			m_frozen = true;
			m_brain.SetMove(Vector2.zero, 0f);
			m_brain.RequestedAttack = -1;
			m_hornCharge = false;
			if (Alive)
			{
				m_health.StartInvincibility("WON");
				((MonoBehaviour)this).StartCoroutine(Gloat());
			}
		}

		private IEnumerator Gloat()
		{
			while (m_busy)
			{
				yield return null;
			}
			yield return (object)new WaitForSeconds(0.8f);
			if (Alive)
			{
				m_player.StartCutscene(Templates.Clips["Roar"], false, 0f);
				Util.PlaySound(Templates.SndGloat, ((Component)this).transform);
			}
		}

		private Vector2 Local(Vector3 world)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			Vector3 position = ((Component)m_room).transform.position;
			return new Vector2(world.x - position.x, world.y - position.y);
		}

		private Vector3 WorldFromLocal(Vector2 local)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			Vector3 position = ((Component)m_room).transform.position;
			return new Vector3(position.x + local.x, position.y + local.y, 0f);
		}

		private void Update()
		{
			if ((Object)(object)m_player == (Object)null)
			{
				return;
			}
			KeepBarVisible();
			if (!Alive || !m_fighting || m_frozen || m_heroDead)
			{
				return;
			}
			try
			{
				Think();
			}
			catch (Exception e)
			{
				Util.WarnOnce("asterion think", e);
			}
		}

		private void KeepBarVisible()
		{
			if (Alive && m_fighting)
			{
				GUIHealthBar shownBar = ShownBar;
				if ((Object)(object)shownBar != (Object)null && (object)s_barTimer != null)
				{
					s_barTimer.SetValue(shownBar, shownBar.m_showTime + 0.1f);
				}
			}
		}

		private void LateUpdate()
		{
			//IL_0046: 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_0073: 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_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			if (Alive && !((Object)(object)m_room == (Object)null) && !((Object)(object)m_bossBar != (Object)null))
			{
				GUIHealthBar gUIHealthBar = m_player.GetGUIHealthBar();
				if (!((Object)(object)gUIHealthBar == (Object)null))
				{
					float num = ((Component)m_room).transform.position.y + ((Rect)(ref m_room.m_cameraBounds)).yMax - 6f;
					Vector3 position = ((Component)this).transform.position;
					float num2 = Mathf.Min(position.y + 48f + 26f, num);
					((Component)gUIHealthBar).transform.position = new Vector3(position.x, num2, ((Component)gUIHealthBar).transform.position.z);
				}
			}
		}

		private void Think()
		{
			//IL_0030: 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_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: 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_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Invalid comparison between Unknown and I4
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Invalid comparison between Unknown and I4
			//IL_0194: 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_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: 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_0216: Unknown result type (might be due to invalid IL or missing references)
			//IL_021b: 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_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0354: Unknown result type (might be due to invalid IL or missing references)
			//IL_0359: Unknown result type (might be due to invalid IL or missing references)
			//IL_035e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0369: Unknown result type (might be due to invalid IL or missing references)
			//IL_036e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0373: Unknown result type (might be due to invalid IL or missing references)
			//IL_0378: Unknown result type (might be due to invalid IL or missing references)
			//IL_0397: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0254: 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_02bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_025e: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f1: 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_0420: Unknown result type (might be due to invalid IL or missing references)
			//IL_0425: Unknown result type (might be due to invalid IL or missing references)
			//IL_0431: Unknown result type (might be due to invalid IL or missing references)
			//IL_0436: Unknown result type (might be due to invalid IL or missing references)
			//IL_0402: Unknown result type (might be due to invalid IL or missing references)
			//IL_0407: Unknown result type (might be due to invalid IL or missing references)
			//IL_040c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0341: Unknown result type (might be due to invalid IL or missing references)
			//IL_0452: Unknown result type (might be due to invalid IL or missing references)
			//IL_0457: Unknown result type (might be due to invalid IL or missing references)
			//IL_0447: Unknown result type (might be due to invalid IL or missing references)
			//IL_0449: Unknown result type (might be due to invalid IL or missing references)
			//IL_045e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0463: Unknown result type (might be due to invalid IL or missing references)
			//IL_0468: Unknown result type (might be due to invalid IL or missing references)
			//IL_0473: Unknown result type (might be due to invalid IL or missing references)
			//IL_0478: Unknown result type (might be due to invalid IL or missing references)
			//IL_047d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0482: Unknown result type (might be due to invalid IL or missing references)
			//IL_04aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_049c: Unknown result type (might be due to invalid IL or missing references)
			Player val = Util.Hero();
			if ((Object)(object)val == (Object)null || (Object)(object)val.GetHealthComponent() == (Object)null || !val.GetHealthComponent().IsAlive())
			{
				m_brain.SetMove(Vector2.zero, 0f);
				return;
			}
			if (m_busy)
			{
				m_wasBusy = true;
				return;
			}
			if (m_pendingPhase > 0)
			{
				((MonoBehaviour)this).StartCoroutine(PhaseRoar(m_pendingPhase));
				m_pendingPhase = 0;
				return;
			}
			if (m_wasBusy)
			{
				m_wasBusy = false;
				m_freeSince = Time.time;
			}
			if (m_hornCharge)
			{
				m_hornCharge = false;
				float num = (m_hornQueuedBusy ? m_freeSince : m_hornRequestTime);
				m_hornQueuedBusy = false;
				Station horn = m_boss.Horn;
				if (Time.time - num < 2.5f && (Object)(object)horn != (Object)null && horn.Ridden)
				{
					Quaternion faceRotation = horn.Trap.GetFaceRotation(-1);
					float num2 = ((Quaternion)(ref faceRotation)).eulerAngles.z * ((float)Math.PI / 180f);
					m_hornChargeUsed = true;
					((MonoBehaviour)this).StartCoroutine(Charge(new Vector2(Mathf.Cos(num2), Mathf.Sin(num2))));
					return;
				}
			}
			Vector2 val2 = Local(((Component)this).transform.position);
			m_maze.CellOf(val2, out var cx, out var cy);
			if (m_maze.Fits(cx, cy))
			{
				m_lastGood = val2;
			}
			ePlayerState state = m_player.GetState();
			bool flag = (int)state == 2 || (int)state == 3;
			Vector2 val3 = Vector2.op_Implicit(((Component)this).transform.position) + new Vector2(0f, 10f);
			Vector2 dir = Vector2.op_Implicit(((Component)val).transform.position) + new Vector2(0f, 8f) - val3;
			float magnitude = ((Vector2)(ref dir)).magnitude;
			Station horn2 = m_boss.Horn;
			bool flag2 = (Object)(object)horn2 != (Object)null && horn2.Ridden;
			Vector2 val4 = Vector2.op_Implicit(((Component)val).transform.position);
			if (flag && m_brain.RequestedAttack < 0)
			{
				if (m_phase >= 2 && Time.time >= m_nextSlam && magnitude < 44f && InReach(val4))
				{
					Face(dir);
					m_brain.RequestedAttack = 1;
					m_nextSlam = Time.time + 6f;
					m_nextCleave = Time.time + 0.8f;
					SelfTest.Note("slam");
					return;
				}
				if (Time.time >= m_nextCleave && magnitude < 30f && InReach(val4))
				{
					Face(dir);
					m_brain.RequestedAttack = 0;
					m_nextCleave = Time.time + 1.8f;
					return;
				}
			}
			if (!flag)
			{
				return;
			}
			if (flag2)
			{
				Vector2 dir2 = horn2.RiderStick();
				m_brain.SetMove(dir2, ((Vector2)(ref dir2)).magnitude);
				return;
			}
			if (Time.time >= m_nextCharge && magnitude > 34f && magnitude < 190f && HeroInOpen(val4) && Clear(val4))
			{
				((MonoBehaviour)this).StartCoroutine(Charge(((Vector2)(ref dir)).normalized));
				return;
			}
			Vector2 dir3 = Vector2.op_Implicit(WorldFromLocal(m_waypoint)) - Vector2.op_Implicit(((Component)this).transform.position);
			bool flag3 = ((Vector2)(ref dir3)).magnitude <= 1.5f;
			bool flag4 = magnitude <= 18f && InReach(val4);
			if (Time.time >= m_nextPath || (flag3 && !flag4 && Time.time >= m_lastPath + 0.05f))
			{
				m_lastPath = Time.time;
				m_nextPath = Time.time + 0.25f;
				Vector2 step;
				bool reachesGoal;
				if (Clear(val4))
				{
					m_waypoint = Local(((Component)val).transform.position);
				}
				else if (m_maze.NextStep(Local(((Component)this).transform.position), Local(((Component)val).transform.position), out step, out reachesGoal))
				{
					m_waypoint = step;
				}
				else
				{
					m_waypoint = m_lastGood;
				}
				dir3 = Vector2.op_Implicit(WorldFromLocal(m_waypoint)) - Vector2.op_Implicit(((Component)this).transform.position);
			}
			if (((Vector2)(ref dir3)).magnitude > 1.5f && !flag4)
			{
				m_brain.SetMove(dir3, 1f);
			}
			else
			{
				Face(dir);
			}
		}

		private void Face(Vector2 dir)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			m_brain.SetMove(dir, 0f);
			m_move.SetDirection(((Vector2)(ref dir)).normalized);
		}

		private bool Clear(Vector2 targetFeet)
		{
			//IL_0006: 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_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: 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_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: 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_0098: 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_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = ((Component)this).transform.position + new Vector3(0f, 2.5f, 0f);
			val.z = 0f;
			Vector3 val2 = new Vector3(targetFeet.x, targetFeet.y + 2.5f, 0f) - val;
			float magnitude = ((Vector3)(ref val2)).magnitude;
			if (magnitude < 0.5f)
			{
				return true;
			}
			float num = 5f;
			Vector3 val3 = val - new Vector3(num, 0f, 0f);
			Vector3 val4 = val + new Vector3(num, 0f, 0f);
			return !Physics.CapsuleCast(val3, val4, 3.5f, val2 / magnitude, magnitude, 512, (QueryTriggerInteraction)1);
		}

		private bool InReach(Vector2 heroFeet)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: 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_0038: 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)
			Vector3 val = new Vector3(((Component)this).transform.position.x, ((Component)this).transform.position.y + 2.5f, 0f);
			Vector3 val2 = default(Vector3);
			((Vector3)(ref val2))..ctor(heroFeet.x, heroFeet.y + 0.5f, 0f);
			return !Physics.Linecast(val, val2, 512, (QueryTriggerInteraction)1);
		}

		private bool HeroInOpen(Vector2 heroFeet)
		{
			//IL_0007: 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_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)
			m_maze.CellOf(Local(new Vector3(heroFeet.x, heroFeet.y, 0f)), out var cx, out var cy);
			return m_maze.FitsNear(cx, cy);
		}

		internal void RequestCharge(Vector2 dir, bool fromHorn)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			if (Alive && !m_frozen && m_fighting && !(((Vector2)(ref dir)).sqrMagnitude < 0.01f))
			{
				m_hornDir = ((Vector2)(ref dir)).normalized;
				m_hornCharge = fromHorn;
				m_hornRequestTime = Time.time;
				m_hornQueuedBusy = m_busy;
			}
		}

		private void DropHornRequest()
		{
			m_hornCharge = false;
			m_hornQueuedBusy = false;
			Station station = (((Object)(object)m_boss != (Object)null) ? m_boss.Horn : null);
			if ((Object)(object)station != (Object)null && (Object)(object)station.Trap != (Object)null)
			{
				try
				{
					station.Trap.GetAttackComponent().SetAttackCooldownOverride(false);
				}
				catch (Exception e)
				{
					Util.WarnOnce("horn refund", e);
				}
			}
		}

		private IEnumerator Charge(Vector2 dir)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			m_busy = true;
			m_brain.RequestedAttack = -1;
			m_brain.SetMove(dir, 0f);
			m_move.SetDirection(dir);
			SelfTest.Note("charge windup");
			m_player.StartStatusAnimation(Templates.Clips["Paw"]);
			float angle = Mathf.Atan2(dir.y, dir.x) * 57.29578f;
			Util.SpawnFx(Templates.TelegraphFx, Vector2.op_Implicit(((Component)this).transform.position) + new Vector2(0f, 4f) + dir * 10f, angle);
			float windup = Templates.Clips["Paw"].length;
			float t0 = Time.time;
			while (Time.time - t0 < windup)
			{
				if (!Alive)
				{
					EndCharge();
					yield break;
				}
				yield return null;
			}
			int charges = ((m_phase < 3) ? 1 : 2);
			for (int n = 0; n < charges; n++)
			{
				if (!Alive)
				{
					break;
				}
				if (n > 0)
				{
					Player val = Util.Hero();
					if ((Object)(object)val == (Object)null)
					{
						break;
					}
					Vector2 val2 = Vector2.op_Implicit(((Component)val).transform.position) - Vector2.op_Implicit(((Component)this).transform.position);
					if (((Vector2)(ref val2)).sqrMagnitude < 1f)
					{
						break;
					}
					dir = ((Vector2)(ref val2)).normalized;
					Face(dir);
					m_player.StartStatusAnimation(Templates.Clips["Paw"]);
					yield return (object)new WaitForSeconds(0.45f);
				}
				bool wall = false;
				yield return ((MonoBehaviour)this).StartCoroutine(Dash(dir, delegate(bool r)
				{
					wall = r;
				}));
				if (!Alive)
				{
					EndCharge();
					yield break;
				}
				if (wall)
				{
					Vector2 hitPoint = Vector2.op_Implicit(((Component)this).transform.position) + dir * 10f;
					yield return ((MonoBehaviour)this).StartCoroutine(Stunned(hitPoint));
					break;
				}
			}
			EndCharge();
			m_nextCharge = Time.time + (m_hornChargeUsed ? 6.5f : 5.5f);
			m_hornChargeUsed = false;
		}

		private IEnumerator Dash(Vector2 dir, Action<bool> result)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			m_player.StartStatusAnimation(Templates.Clips["Charge"]);
			m_player.AnimCollideOff();
			float num = 3.6f * ((m_phase >= 3) ? 1.2f : 1f);
			m_move.SetSpeedMultiplier(num);
			m_move.SetInputOverride(dir);
			m_player.SpawnEffect(Util.Get<List<DamageEffectData>>(m_player, "m_attackDamageEffects")[1]);
			m_player.SpawnEffect(Util.Get<List<DamageEffectData>>(m_player, "m_attackDamageEffects")[3]);
			SelfTest.Note("charge");
			float expected = 60f * num;
			float t = 0f;
			float nextPuff = 0f;
			int slowFrames = 0;
			bool hitWall = false;
			while (t < 1.7f)
			{
				yield return (object)new WaitForFixedUpdate();
				if (!Alive)
				{
					break;
				}
				t += Time.fixedDeltaTime;
				if (t >= nextPuff)
				{
					nextPuff = t + 0.1f;
					Util.SpawnFx(Templates.SmokeFx, Vector2.op_Implicit(((Component)this).transform.position) - dir * 8f);
				}
				Vector3 val = ((Component)this).transform.position + new Vector3(0f, 2.5f, 0f);
				val.z = 0f;
				float num2 = 9f + expected * Time.fixedDeltaTime + 2f;
				if (Physics.Raycast(val, new Vector3(dir.x, dir.y, 0f), num2, 16777728, (QueryTriggerInteraction)1))
				{
					hitWall = true;
					break;
				}
				Vector2 val2 = (((Object)(object)m_body != (Object)null) ? Vector2.op_Implicit(m_body.velocity) : m_move.GetVelocity());
				if (t > 0.2f && Vector2.Dot(val2, dir) < expected * 0.3f)
				{
					int num3 = slowFrames + 1;
					slowFrames = num3;
					if (num3 >= 3)
					{
						float num4 = 5f;
						Vector3 val3 = ((Component)this).transform.position + new Vector3(0f, 2.5f, 0f);
						val3.z = 0f;
						hitWall = Physics.CapsuleCast(val3 - new Vector3(num4, 0f, 0f), val3 + new Vector3(num4, 0f, 0f), 3.6f, new Vector3(dir.x, dir.y, 0f), 4f, 16777728, (QueryTriggerInteraction)1);
						break;
					}
				}
				else
				{
					slowFrames = 0;
				}
			}
			m_move.ResetInputOverride();
			m_move.ResetSpeedMultiplier();
			m_move.Stop();
			m_player.AnimCollideOn();
			result(hitWall);
		}

		private IEnumerator Stunned(Vector2 hitPoint)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			SelfTest.Note("wall impact -> stunned");
			Util.PlaySound(Templates.SndWallHit, ((Component)this).transform);
			Util.PlaySound(Templates.SndRumble, ((Component)this).transform);
			Util.SpawnFx(Templates.DustFx, hitPoint);
			Util.SpawnFx(Templates.DebrisFx, hitPoint);
			m_player.AnimShake3(0.4f);
			m_player.StartStatusAnimation(Templates.Clips["Impact"]);
			yield return (object)new WaitForSeconds(Templates.Clips["Impact"].length);
			if (Alive)
			{
				AllowStun = true;
				m_player.Stun(3.6f, false);
				AllowStun = false;
				m_anim.Play(Templates.Clips["Stunned"]);
				m_health.AnimVulnerableOn();
				m_vulnerable = true;
				DropHornRequest();
				m_boss.OnAsterionVulnerable(vulnerable: true);
				float t0 = Time.time;
				while (Alive && (int)m_player.GetState() == 6 && Time.time - t0 < 4.6f)
				{
					yield return null;
				}
				m_vulnerable = false;
				m_health.AnimVulnerableOff();
				m_boss.OnAsterionVulnerable(vulnerable: false);
				if (Alive)
				{
					m_player.StartStatusAnimation(Templates.Clips["Recover"]);
					yield return (object)new WaitForSeconds(Templates.Clips["Recover"].length);
				}
			}
		}

		private void EndCharge()
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Invalid comparison between Unknown and I4
			m_move.ResetInputOverride();
			m_move.ResetSpeedMultiplier();
			if ((Object)(object)m_player != (Object)null && Alive)
			{
				m_player.AnimCollideOn();
				if ((int)m_player.GetState() == 15)
				{
					m_player.EndCutscene();
				}
			}
			m_vulnerable = false;
			m_busy = false;
		}

		private void OnDamaged(DamageInfo info)
		{
			if (!m_dead && !((Object)(object)m_health == (Object)null))
			{
				if ((Object)(object)Templates.SndHurt != (Object)null && info != null && info.m_source != null && info.m_source.m_sourcePlayer != null && (info.m_amount != 0f || (Object)(object)info.m_status != (Object)null || info.m_stunTime > 0f) && Time.time - m_lastHurtSound >= 0.25f)
				{
					m_lastHurtSound = Time.time;
					Util.PlaySound(Templates.SndHurt, ((Component)this).transform);
				}
				float num = m_health.GetHealthRatio();
				if (HoldingPhaseFloor && m_health.GetHealthCurrent() < PhaseFloor)
				{
					m_health.ChangeHealth(PhaseFloor);
					num = PhaseFloor / m_health.GetHealthMax();
				}
				int num2 = ((num <= 1f / 3f) ? 3 : ((!(num <= 2f / 3f)) ? 1 : 2));
				if (num2 > m_phase)
				{
					m_phase = num2;
					m_pendingPhase = num2;
					m_boss.OnPhase(num2);
				}
				if (HoldingPhaseFloor)
				{
					m_health.SetMaxDamagePerHit(Mathf.Clamp(m_health.GetHealthCurrent() - PhaseFloor, 0.001f, 6f));
				}
			}
		}

		internal void ReleasePhaseFloor()
		{
			if ((Object)(object)m_health != (Object)null)
			{
				m_health.SetMaxDamagePerHit(6f);
			}
		}

		private IEnumerator PhaseRoar(int phase)
		{
			m_busy = true;
			m_brain.SetMove(Vector2.zero, 0f);
			m_health.StartInvincibility("roar");
			m_player.StartCutscene(Templates.Clips["Roar"], false, 0f);
			Util.PlaySound(Templates.SndGrowl, ((Component)this).transform);
			yield return (object)new WaitForSeconds(Templates.Clips["Roar"].length);
			m_health.StopInvincibility("roar");
			if (Alive && (int)m_player.GetState() == 13)
			{
				m_player.EndCutscene();
			}
			if (phase >= 3)
			{
				ColorTinterBase val = ((Component)this).GetComponent<ColorTinterBase>();
				if ((Object)(object)val == (Object)null)
				{
					val = ((Component)this).gameObject.AddComponent<ColorTinterBase>();
				}
				val.AddTint(new Color(0.9f, 0.15f, 0.1f, 0.28f));
			}
			m_nextCharge = Mathf.Min(m_nextCharge, Time.time + 0.5f);
			m_busy = false;
		}

		private void OnDie(Player p, DamageInfo info)
		{
			if (!m_dead)
			{
				m_dead = true;
				m_vulnerable = false;
				((MonoBehaviour)this).StopAllCoroutines();
				m_move.ResetInputOverride();
				m_move.ResetSpeedMultiplier();
				if ((Object)(object)m_boss != (Object)null)
				{
					m_boss.OnAsterionKilled();
				}
			}
		}

		private void MsgOnObjectSpawn(GameObject obj)
		{
			//IL_0074: 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_0080: 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_00a7: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)obj == (Object)null))
			{
				float num = 0f;
				string name = ((Object)obj).name;
				if (name.StartsWith(((Object)Templates.CleaveFx).name, StringComparison.Ordinal))
				{
					num = 2.2f;
				}
				else if (name.StartsWith(((Object)Templates.ChargeFx).name, StringComparison.Ordinal))
				{
					num = 2.2f;
				}
				else if (name.StartsWith(((Object)Templates.SlamFx).name, StringComparison.Ordinal))
				{
					num = 1.6f;
				}
				if (num > 0f)
				{
					Vector3 localScale = obj.transform.localScale;
					obj.transform.localScale = new Vector3(Mathf.Sign((localScale.x == 0f) ? 1f : localScale.x) * num, num, 1f);
				}
			}
		}

		private void OnDestroy()
		{
			Patches.UnregisterAsterion(this);
		}
	}
	public class LabyrinthBoss : Boss
	{
		internal static LabyrinthBoss Current;

		private Room m_room;

		private Maze m_maze;

		private Maze.Built m_built;

		private readonly List<Station> m_stations = new List<Station>();

		private readonly List<TrapGroup> m_groups = new List<TrapGroup>();

		private Station m_horn;

		private Asterion m_asterion;

		private GUIHealthBar m_bossBar;

		private bool m_spawned;

		private bool m_killed;

		private bool m_heroDead;

		private int m_phase = 1;

		private int m_phaseGen;

		private bool m_phaseSettling;

		private float m_settleTime;

		private TrapGroup m_botPressGroup;

		private float m_botPressTime = -100f;

		internal List<TrapGroup> Groups => m_groups;

		internal Room Arena => m_room;

		internal Maze MazeData => m_maze;

		internal Asterion Body => m_asterion;

		internal bool Killed => m_killed;

		internal Station Horn => m_horn;

		internal float PromptCeiling
		{
			get
			{
				//IL_002b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				float num = (((Object)(object)m_room != (Object)null) ? ((Component)m_room).transform.position.y : ((Component)this).transform.position.y);
				if ((Object)(object)m_bossBar != (Object)null)
				{
					return num + Tuning.BossBarLocal.y - 3.5f - 6f;
				}
				return num + (((Object)(object)m_room != (Object)null) ? ((Rect)(ref m_room.m_cameraBounds)).yMax : 107f) - 8f;
			}
		}

		internal int Phase => m_phase;

		internal bool PhaseSettling
		{
			get
			{
				if (m_phaseSettling)
				{
					return !FightOver;
				}
				return false;
			}
		}

		private bool FightOver
		{
			get
			{
				if (!m_killed && !base.m_won)
				{
					return m_heroDead;
				}
				return true;
			}
		}

		internal static void Configure(LabyrinthBoss b)
		{
			//IL_0046: 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)
			Util.Set(b, "m_displayName", "- Challenge ASTERION -");
			Util.Set(b, "m_bossUnleashedSceneName", "SceneMenuLose");
			Util.Set(b, "m_bossRoom", Templates.ArenaTemplate);
			Util.Set(b, "m_entryRoom", Templates.EntryRoom);
			Util.Set(b, "m_bossPosition", Templates.BossPositionLocal);
			Util.Set(b, "m_entryRoomProps", Templates.EntryRoomProps);
			Util.Set(b, "m_bossRoomProps", Templates.BossRoomProps);
			Util.Set(b, "m_playerEntryRoomOffset", Templates.PlayerEntryRoomOffset);
			Util.Set(b, "m_heroWinPauseTime", Templates.HeroWinPause);
			Util.Set(b, "m_heroWinRunAroundTime", Templates.HeroWinRunAround);
			Util.Set(b, "m_roomDoorSealPrefab", Templates.DoorSeal);
			Util.Set(b, "m_minPlayersRequired", 0);
			Util.Set(b, "m_heroWinEffect", Templates.HeroWinEffect);
			Util.Set(b, "m_heroWinEffectDelay", Templates.HeroWinEffectDelay);
			Util.Set(b, "m_bossWinEffect", Templates.BossWinEffect);
			Util.Set(b, "m_bossWinEffectDelay", Templates.BossWinEffectDelay);
			Util.Set(b, "m_musicBossOverride", null);
		}

		private void Awake()
		{
			if (Templates.Ready)
			{
				Configure(this);
			}
		}

		private void Start()
		{
			if ((Object)(object)((Component)this).transform.parent == (Object)null || !Templates.Ready)
			{
				return;
			}
			m_room = ((Component)((Component)this).transform.parent).GetComponent<Room>();
			if ((Object)(object)m_room == (Object)null)
			{
				Util.Warn("Asterion's boss controller is not under a room");
				return;
			}
			Current = this;
			Templates.ApplyBossDamage();
			try
			{
				m_maze = Maze.Load();
				m_built = m_maze.Build(m_room);
				Patches.ArenaRoom = m_room;
				Patches.MarkPathfinderDirty();
				SpawnStations();
				Util.Info("Labyrinth built: " + m_built.Walls.Count + " wall colliders, " + m_built.Gates.Count + " gates, " + m_stations.Count + " stations");
				SelfTest.Note("labyrinth built");
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Labyrinth build failed: " + ex));
			}
		}

		private void SpawnStations()
		{
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: Unknown result type (might be due to invalid IL or missing references)
			//IL_023f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0244: Unknown result type (might be due to invalid IL or missing references)
			//IL_0266: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ba: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<string, TrapGroup> dictionary = new Dictionary<string, TrapGroup>();
			foreach (GroupSpec group in m_maze.Groups)
			{
				if (!Templates.GroupKinds.TryGetValue(group.Id, out var value) || !Templates.Stations.ContainsKey(Templates.GroupTemplateKey(group.Id)))
				{
					Util.Warn("trap group " + group.Id + " (" + group.Name + ") has no template; its cells stay plain wall");
				}
				else
				{
					TrapGroup trapGroup = new TrapGroup(group, value);
					dictionary[group.Id] = trapGroup;
					m_groups.Add(trapGroup);
				}
			}
			foreach (StationSpec station2 in m_maze.Stations)
			{
				bool flag = station2.Type.StartsWith("Lever", StringComparison.Ordinal);
				TrapGroup value2 = null;
				if (!flag && (station2.Group == null || !dictionary.TryGetValue(station2.Group, out value2)))
				{
					SpawnStandIn(station2, on: true);
					continue;
				}
				string text = (flag ? "Lever" : Templates.GroupTemplateKey(value2.Id));
				GameObject val = SpawnStandIn(station2, on: false);
				if (!Templates.Stations.TryGetValue(text, out var value3))
				{
					Util.Warn("no station template " + text);
					val.SetActive(true);
					continue;
				}
				Vector3 val2 = m_maze.World(m_room, m_maze.CellMin(station2.Cx, station2.Cy) + new Vector2(4f, flag ? 0f : 1f));
				GameObject val3 = m_room.SpawnInRoom(value3, val2);
				if ((Object)(object)val3 == (Object)null)
				{
					val.SetActive(true);
					continue;
				}
				GameObject val4 = new GameObject("LabyStationBlocker")
				{
					layer = 9
				};
				val4.transform.SetParent(val3.transform, false);
				val4.transform.position = m_maze.World(m_room, m_maze.CellCenter(station2.Cx, station2.Cy));
				BoxCollider val5 = val4.AddComponent<BoxCollider>();
				val5.size = new Vector3(8f, 8f, 50f);
				bool flag2 = m_maze.IsWallVisual(station2.Cx, station2.Cy - 1);
				exSprite component = val3.GetComponent<exSprite>();
				if ((Object)(object)component != (Object)null && flag2)
				{
					((exPlane)component).offset = ((exPlane)component).offset + new Vector2(0f, 10f);
				}
				DepthHandler component2 = val3.GetComponent<DepthHandler>();
				if ((Object)(object)component2 != (Object)null)
				{
					Util.Set(component2, "m_finalHeightOffset", component2.m_heightOffset = (flag2 ? (-10f) : (-2f)));
				}
				if (((Component)m_room).gameObject.layer == 12)
				{
					exSprite[] componentsInChildren = val3.GetComponentsInChildren<exSprite>(true);
					for (int i = 0; i < componentsInChildren.Length; i++)
					{
						((Behaviour)componentsInChildren[i]).enabled = false;
					}
				}
				Station station = val3.AddComponent<Station>();
				station.Cx = station2.Cx;
				station.Cy = station2.Cy;
				station.StandIn = val;
				station.Init(this, flag ? Station.Kind.Lever : Station.Kind.Trap, station2.Phase, flag ? int.Parse(station2.Type.Substring(5)) : (-1), station2.Aim, value2);
				station.SetBlocker(val5);
				m_stations.Add(station);
				if (value2 != null)
				{
					value2.Members.Add(station);
					if (value2.Phase > 1)
					{
						station.SetLocked(locked: true);
						val3.SetActive(false);
						val.SetActive(true);
					}
				}
			}
			foreach (TrapGroup group2 in m_groups)
			{
				group2.Members.Sort((Station a, Station b) => (a.Cy == b.Cy) ? a.Cx.CompareTo(b.Cx) : b.Cy.CompareTo(a.Cy));
				group2.Live = group2.Phase == 1 && group2.Members.Count > 0;
				string[] obj = new string[10] { "Trap group ", group2.Id, " (", group2.Name, "): phase ", null, null, null, null, null };
				int i = group2.Phase;
				obj[5] = i.ToString();
				obj[6] = ", ";
				obj[7] = group2.Members.Count.ToString();
				obj[8] = " x ";
				obj[9] = group2.Kind;
				Util.Info(string.Concat(obj));
			}
		}

		private GameObject SpawnStandIn(StationSpec s, bool on)
		{
			//IL_001e: 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_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)
			//IL_0045: 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_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: 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_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Expected O, but got Unknown
			Vector3 val = m_maze.World(m_room, m_maze.CellMin(s.Cx, s.Cy));
			m_room.AddPropRect(new Rect(val.x, val.y, 8f, 8f));
			GameObject val2 = new GameObject("LabyStationStandIn")
			{
				layer = 9
			};
			val2.transform.SetParent(((Component)m_room).transform, false);
			val2.transform.position = m_maze.World(m_room, m_maze.CellCenter(s.Cx, s.Cy));
			val2.AddComponent<BoxCollider>().size = new Vector3(8f, 8f, 50f);
			val2.SetActive(on);
			return val2;
		}

		internal void NoteBotPress(TrapGroup g)
		{
			m_botPressGroup = g;
			m_botPressTime = Time.time;
		}

		internal bool OtherGroupFiredWithin(TrapGroup g, float seconds)
		{
			float time = Time.time;
			if (m_botPressGroup != null && m_botPressGroup != g && time - m_botPressTime < seconds)
			{
				return true;
			}
			for (int i = 0; i < m_groups.Count; i++)
			{
				if (m_groups[i] != g && time - m_groups[i].LastVolley < seconds)
				{
					return true;
				}
			}
			return false;
		}

		internal Gate GateAt(int index)
		{
			if (m_built == null || index < 0 || index >= m_built.Gates.Count)
			{
				return null;
			}
			return m_built.Gates[index];
		}

		public override void OnEnterBossRoom()
		{
			if (SystemLevel.GetHeroPlayerData() != null && !((Object)(object)SystemLevel.GetHeroObject() == (Object)null) && !((Object)(object)m_room == (Object)null))
			{
				((Boss)this).OnEnterBossRoom();
				if (!m_spawned)
				{
					m_spawned = true;
					SpawnAsterion();
					((MonoBehaviour)this).StartCoroutine(Intro());
				}
				else if ((Object)(object)m_asterion != (Object)null)
				{
					m_asterion.SetFrozen(frozen: false);
				}
			}
		}

		public override void OnExitBossRoom()
		{
			((Boss)this).OnExitBossRoom();
			if ((Object)(object)m_asterion != (Object)null)
			{
				m_asterion.SetFrozen(frozen: true);
			}
		}

		public override void OnHeroKilled(Player killed, DamageInfo damage)
		{
			((Boss)this).OnHeroKilled(killed, damage);
			((Boss)this).StopKillingBlowEffects(killed, damage);
			m_heroDead = true;
			SetStationsEnabled(enabled: false);
			if ((Object)(object)m_asterion != (Object)null)
			{
				m_asterion.OnHeroKilled();
			}
			SelfTest.Note("hero killed");
		}

		public override bool GetAttackable()
		{
			if (base.m_inRoom && (Object)(object)m_asterion != (Object)null)
			{
				return m_asterion.Alive;
			}
			return false;
		}

		public override bool GetVulnerable()
		{
			if ((Object)(object)m_asterion != (Object)null)
			{
				return m_asterion.Vulnerable;
			}
			return false;
		}

		public override Vector2 GetVulnerableTargetPosition()
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)m_asterion != (Object)null))
			{
				return Vector2.op_Implicit(((Component)this).transform.position);
			}
			return Vector2.op_Implicit(((Component)m_asterion).transform.position);
		}

		public override Vector2 GetNonVulnerableTargetPosition()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			return ((Boss)this).GetVulnerableTargetPosition();
		}

		public override bool GetWaitUntilFullyInRoom()
		{
			return true;
		}

		private void SpawnAsterion()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: 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)
			Vector3 val = m_maze.World(m_room, m_maze.AsterionStart);
			GameObject val2 = ExtentionsMethodsPool.Spawn(Templates.BodyTemplate, val, Quaternion.identity);
			((Object)val2).name = "Asterion";
			val2.AddComponent<AsterionBrain>();
			m_asterion = val2.AddComponent<Asterion>();
			m_asterion.Setup(this, m_maze, m_room);
			val2.GetComponent<Player>().InitAsAI((GameObject)null);
			m_asterion.AfterInit();
			m_bossBar = SpawnBossBar(val2.GetComponent<Health>());
			m_asterion.SetBossBar(m_bossBar);
			SpawnHorn();
		}

		private GUIHealthBar SpawnBossBar(Health health)
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: 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)
			if ((Object)(object)Templates.BossBarTemplate == (Object)null || (Object)(object)health == (Object)null)
			{
				return null;
			}
			try
			{
				GameObject obj = Object.Instantiate<GameObject>(Templates.BossBarTemplate);
				((Object)obj).name = "AsterionBossBar";
				obj.transform.SetParent(((Component)this).transform, false);
				Vector3 position = ((Component)m_room).transform.position;
				obj.transform.position = new Vector3(position.x + Tuning.BossBarLocal.x, position.y + Tuning.BossBarLocal.y, -100f);
				GUIHealthBar component = obj.GetComponent<GUIHealthBar>();
				component.SetHealthComponent(health);
				return component;
			}
			catch (Exception e)
			{
				Util.WarnOnce("boss bar", e);
				return null;
			}
		}

		private void SpawnHorn()
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			if (!Templates.Stations.TryGetValue("Horn", out var value))
			{
				return;
			}
			GameObject val = m_room.SpawnInRoom(value, ((Component)m_asterion).transform.position);
			if (!((Object)(object)val == (Object)null))
			{
				Transform val2 = val.transform.Find("Body");
				if ((Object)(object)val2 != (Object)null)
				{
					((Component)val2).gameObject.SetActive(false);
				}
				DepthHandler component = val.GetComponent<DepthHandler>();
				if ((Object)(object)component != (Object)null)
				{
					component.m_heightOffset = -3f;
					Util.Set(component, "m_finalHeightOffset", -3f);
				}
				m_horn = val.AddComponent<Station>();
				m_horn.Init(this, Station.Kind.Horn, 1, -1, 0f);
				m_stations.Add(m_horn);
			}
		}

		private IEnumerator Intro()
		{
			((MonoBehaviour)this).StartCoroutine(((Boss)this).CoroutineHeroEnterSequence());
			yield return (object)new WaitForSeconds(0.6f);
			if ((Object)(object)m_asterion != (Object)null)
			{
				m_asterion.PlayIntroRoar();
			}
			yield return (object)new WaitForSeconds(1.7f);
			((Boss)this).OnSpawnComplete();
			if ((Object)(object)m_asterion != (Object)null && !base.m_won)
			{
				m_asterion.StartFight();
			}
			SelfTest.Note("fight started");
		}

		internal void OnPhase(int phase)
		{
			m_phase = phase;
			int gen = ++m_phaseGen;
			m_phaseSettling = true;
			m_settleTime = 0f;
			try
			{
				((MonoBehaviour)this).StartCoroutine(ShiftGroups(phase, gen));
			}
			catch (Exception e)
			{
				Util.WarnOnce("phase shift", e);
				EndPhaseSettling();
			}
			if (m_built != null)
			{
				foreach (Gate gate in m_built.Gates)
				{
					gate.ForceOpen();
				}
			}
			Patches.MarkPathfinderDirty();
			SelfTest.Note("phase " + phase);
		}

		private void EndPhaseSettling()
		{
			m_phaseSettling = false;
			if ((Object)(object)m_asterion != (Object)null)
			{
				m_asterion.ReleasePhaseFloor();
			}
		}

		private static float Tick()
		{
			if (!SystemTime.Paused)
			{
				return Time.deltaTime;
			}
			return 0f;
		}

		private IEnumerator ShiftGroups(int phase, int gen)
		{
			float t = 0f;
			List<TrapGroup> outgoing = new List<TrapGroup>();
			foreach (TrapGroup group in m_groups)
			{
				if (group.Phase == phase)
				{
					continue;
				}
				bool flag = false;
				foreach (Station member in group.Members)
				{
					if ((Object)(object)member != (Object)null && ((Component)member).gameObject.activeSelf)
					{
						flag = true;
						member.SetLocked(locked: true);
						AnimStateMachine states = member.States;
						switch (((Object)(object)states != (Object)null) ? states.GetStateName() : string.Empty)
						{
						case "Activate":
						case "Active":
						case "Action":
							states.SetState("Deactivate");
							break;
						}
					}
				}
				group.Live = false;
				group.Invalidate();
				if (flag)
				{
					outgoing.Add(group);
					((MonoBehaviour)this).StartCoroutine(PuffAlong(group));
				}
			}
			for (; t < 0.3f; t += Tick())
			{
				yield return null;
			}
			if (gen != m_phaseGen)
			{
				yield break;
			}
			foreach (TrapGroup item in outgoing)
			{
				foreach (Station member2 in item.Members)
				{
					if ((Object)(object)member2 != (Object)null && ((Component)member2).gameObject.activeSelf)
					{
						((Component)member2).gameObject.SetActive(false);
						if ((Object)(object)member2.StandIn != (Object)null)
						{
							member2.StandIn.SetActive(true);
						}
					}
				}
			}
			Patches.MarkPathfinderDirty();
			List<TrapGroup> incoming = new List<TrapGroup>();
			foreach (TrapGroup group2 in m_groups)
			{
				if (group2.Phase == phase)
				{
					incoming.Add(group2);
				}
			}
			for (int i = 0; i < incoming.Count; i++)
			{
				for (float groupStart = 0.6f + (float)i * 0.3f; t < groupStart; t += Tick())
				{
					yield return null;
				}
				TrapGroup g = incoming[i];
				for (int j = 0; j < g.Members.Count; j++)
				{
					if (FightOver || gen != m_phaseGen)
					{
						if (gen == m_phaseGen)
						{
							EndPhaseSettling();
						}
						yield break;
					}
					Station station = g.Members[j];
					if ((Object)(object)station != (Object)null && !((Component)station).gameObject.activeSelf)
					{
						station.SetLocked(locked: true);
						if ((Object)(object)station.StandIn != (Object)null)
						{
							station.StandIn.SetActive(false);
						}
						((Component)station).gameObject.SetActive(true);
						Util.SpawnFx(Templates.DespawnFx, Vector2.op_Implicit(((Component)station).transform.position));
						((MonoBehaviour)this).StartCoroutine(WakeOnce(station));
					}
					for (float next = t + 0.08f; t < next; t += Tick())
					{
						yield return null;
					}
				}
			}
			Patches.MarkPathfinderDirty();
			for (; t < 1.5f; t += Tick())
			{
				yield return null;
			}
			if (FightOver || gen != m_phaseGen)
			{
				if (gen == m_phaseGen)
				{
					EndPhaseSettling();
				}
				yield break;
			}
			foreach (TrapGroup item2 in incoming)
			{
				foreach (Station member3 in item2.Members)
				{
					if ((Object)(object)member3 != (Object)null && ((Component)member3).gameObject.activeSelf)
					{
						member3.ClearExitGuard();
						member3.SetLocked(locked: false);
					}
				}
				item2.Live = item2.Members.Count > 0;
				item2.Invalidate();
			}
			EndPhaseSettling();
			SelfTest.Note("phase " + phase + " groups live: " + string.Join(", ", incoming.ConvertAll((TrapGroup trapGroup) => trapGroup.Id + " " + trapGroup.Kind).ToArray()));
		}

		private IEnumerator PuffAlong(TrapGroup g)
		{
			List<Station> list = new List<Station>(g.Members);
			foreach (Station s in list)
			{
				while (SystemTime.Paused)
				{
					yield return null;
				}
				if ((Object)(object)s != (Object)null && ((Component)s).gameObject.activeInHierarchy)
				{
					Util.SpawnFx(Templates.DespawnFx, Vector2.op_Implicit(((Component)s).transform.position));
				}
				for (float waited = 0f; waited < 0.08f; waited += Tick())
				{
					yield return null;
				}
			}
		}

		private IEnumerator WakeOnce(Station s)
		{
			float waited = 0f;
			while ((Object)(object)s != (Object)null && ((Component)s).gameObject.activeInHierarchy && (SystemTime.Paused || (waited < 1f && ((Object)(object)s.States == (Object)null || s.States.GetStateName() != "Inactive"))))
			{
				yield return null;
				waited += Tick();
			}
			if ((Object)(object)s == (Object)null || !((Component)s).gameObject.activeInHierarchy || (Object)(object)s.States == (Object)null || s.States.GetStateName() != "Inactive" || s.Trap.GetInhabited())
			{
				yield break;
			}
			try
			{
				s.States.SetState("Activate");
			}
			catch (Exception e)
			{
				Util.WarnOnce("station wake", e);
			}
		}

		internal void OnAsterionKilled()
		{
			if (m_killed)
			{
				return;
			}
			m_killed = true;
			try
			{
				SetStationsEnabled(enabled: false);
				if (m_built != null)
				{
					foreach (Gate gate in m_built.Gates)
					{
						gate.ForceOpen();
					}
				}
			}
			catch (Exception e)
			{
				Util.WarnOnce("boss killed cleanup", e);
			}
			finally
			{
				Singleton<SystemLevel>.Get.OnBossKilled();
			}
			SelfTest.Note("asterion killed");
		}

		internal void OnAsterionVulnerable(bool vulnerable)
		{
			if ((Object)(object)m_horn != (Object)null && !m_killed && !base.m_won)
			{
				m_horn.SetSuspended(vulnerable);
			}
		}

		private void SetStationsEnabled(bool enabled)
		{
			foreach (Station station in m_stations)
			{
				if ((Object)(object)station != (Object)null)
				{
					station.SetSuspended(!enabled);
				}
			}
		}

		private void LateUpdate()
		{
			if ((Object)(object)m_horn != (Object)null && (Object)(object)m_asterion != (Object)null)
			{
				m_horn.FollowAsterion(m_asterion);
			}
			if (!m_phaseSettling)
			{
				return;
			}
			m_settleTime += Tick();
			if (m_settleTime > 3f || FightOver)
			{
				if (!FightOver)
				{
					Util.Warn("phase " + m_phase + " groups did not go live in time; lifting the health floor");
				}
				EndPhaseSettling();
			}
		}

		private void OnDestroy()
		{
			if ((Object)(object)Current == (Object)(object)this)
			{
				Current = null;
				Patches.ArenaRoom = null;
			}
			if (!((Object)(object)m_asterion != (Object)null) || !((Object)(object)((Component)m_asterion).gameObject != (Object)null))
			{
				return;
			}
			try
			{
				if (m_asterion.Alive)
				{
					ExtentionsMethodsPool.Despawn(((Component)m_asterion).gameObject);
				}
			}
			catch (Exception e)
			{
				Util.WarnOnce("despawn asterion", e);
			}
		}
	}
	internal struct CellRect
	{
		public int x;

		public int y;

		public int width;

		public int height;

		public CellRect(int x, int y, int width, int height)
		{
			this.x = x;
			this.y = y;
			this.width = width;
			this.height = height;
		}
	}
	internal class StationSpec
	{
		public string Type;

		public int Cx;

		public int Cy;

		public int Phase;

		public float Aim;

		public string Group;
	}
	internal class GroupSpec
	{
		public string Id;

		public int Phase;

		public string Type;

		public float[] Aims;

		public string Name;

		public readonly List<StationSpec> Members = new List<StationSpec>();
	}
	internal class Maze
	{
		public class GateSpec
		{
			public bool Horizontal;

			public int Cx;

			public int Cy;

			public int Length;
		}

		public class Built
		{
			public Room Room;

			public readonly List<GameObject> Walls = new List<GameObject>();

			public readonly List<Gate> Gates = new List<Gate>();
		}

		public const float X0 = -136f;

		public const float Y0 = -64f;

		public const float Cell = 8f;

		public const float WallHeight = 10f;

		private char[,] m_grid;

		public readonly List<StationSpec> Stations = new List<StationSpec>();

		public readonly List<GroupSpec> Groups = new List<GroupSpec>();

		private readonly HashSet<long> m_stationCells = new HashSet<long>();

		public Vector2 AsterionStart;

		private bool[] m_gateClosed = new bool[0];

		private List<GateSpec> m_gateCache;

		private static readonly int[] DX = new int[4] { 1, -1, 0, 0 };

		private static readonly int[] DY = new int[4] { 0, 0, 1, -1 };

		public int Cols { get; private set; }

		public int Rows { get; private set; }

		public static Maze Load()
		{
			//IL_05bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_05c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			Maze maze = new Maze();
			List<string> list = (from l in Util.ResourceText("maze.txt").Replace("\r", "").Split(new char[1] { '\n' })
				where l.Length > 0 && !l.StartsWith(";")
				select l).ToList();
			maze.Rows = list.Count;
			maze.Cols = list.Max((string r) => r.Length);
			maze.m_grid = new char[maze.Cols, maze.Rows];
			for (int num = 0; num < maze.Rows; num++)
			{
				int num2 = maze.Rows - 1 - num;
				for (int num3 = 0; num3 < maze.Cols; num3++)
				{
					char c = ((num3 < list[num].Length) ? list[num][num3] : ' ');
					maze.m_grid[num3, num2] = c;
					if (c == 'A')
					{
						maze.AsterionStart = maze.CellCenter(num3, num2);
					}
				}
			}
			string[] array = Util.ResourceText("stations.txt").Replace("\r", "").Split(new char[1] { '\n' });
			foreach (string obj in array)
			{
				string text = obj.Trim();
				if (text.Length == 0 || text.StartsWith(";"))
				{
					continue;
				}
				string[] p = text.Split(new char[2] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
				if (p[0] == "Group")
				{
					if (p.Length < 6)
					{
						throw new FormatException("stations.txt: short Group line: " + text);
					}
					GroupSpec g = new GroupSpec
					{
						Id = p[1],
						Phase = int.Parse(p[2]),
						Type = p[3],
						Aims = ParseAngles(p[4]),
						Name = ((p.Length > 6) ? string.Join(" ", p, 6, p.Length - 6) : p[1])
					};
					if (maze.Groups.Any((GroupSpec x) => x.Id == g.Id))
					{
						throw new FormatException("stations.txt: group " + g.Id + " is defined twice");
					}
					maze.Groups.Add(g);
					continue;
				}
				if (p.Length < 5)
				{
					throw new FormatException("stations.txt: short station line: " + text);
				}
				StationSpec stationSpec = new StationSpec
				{
					Type = p[0],
					Cx = int.Parse(p[1]),
					Cy = int.Parse(p[2]),
					Phase = int.Parse(p[3]),
					Aim = float.Parse(p[4], CultureInfo.InvariantCulture)
				};
				if (maze.At(stationSpec.Cx, stationSpec.Cy) != '#')
				{
					throw new FormatException("station " + stationSpec.Type + " at " + stationSpec.Cx + "," + stationSpec.Cy + " is not on a wall cell");
				}
				if (maze.IsStation(stationSpec.Cx, stationSpec.Cy))
				{
					throw new FormatException("station " + stationSpec.Type + " at " + stationSpec.Cx + "," + stationSpec.Cy + " shares its cell with another station");
				}
				if (!stationSpec.Type.StartsWith("Lever", StringComparison.Ordinal))
				{
					GroupSpec groupSpec = ((p.Length > 5) ? maze.Groups.FirstOrDefault((GroupSpec x) => x.Id == p[5]) : null);
					if (groupSpec == null)
					{
						Util.Warn("stations.txt: trap " + stationSpec.Type + " at " + stationSpec.Cx + "," + stationSpec.Cy + " names no defined group, skipped");
						continue;
					}
					if (groupSpec.Type != stationSpec.Type || groupSpec.Phase != stationSpec.Phase)
					{
						Util.Warn("stations.txt: trap at " + stationSpec.Cx + "," + stationSpec.Cy + " does not match group " + groupSpec.Id + "; it takes the group's kind and phase");
						stationSpec.Type = groupSpec.Type;
						stationSpec.Phase = groupSpec.Phase;
					}
					stationSpec.Group = groupSpec.Id;
					groupSpec.Members.Add(stationSpec);
				}
				maze.Stations.Add(stationSpec);
				maze.m_stationCells.Add(Key(stationSpec.Cx, stationSpec.Cy));
			}
			if (maze.AsterionStart == Vector2.zero)
			{
				throw new FormatException("maze.txt has no 'A' cell");
			}
			return maze;
		}

		private static float[] ParseAngles(string s)
		{
			if (string.IsNullOrEmpty(s) || s == "-")
			{
				return null;
			}
			return (from a in s.Split(new char[1] { ',' })
				select float.Parse(a, CultureInfo.InvariantCulture)).ToArray();
		}

		private static long Key(int cx, int cy)
		{
			return ((long)cx << 32) | (uint)cy;
		}

		public char At(int cx, int cy)
		{
			if (cx < 0 || cy < 0 || cx >= Cols || cy >= Rows)
			{
				return ' ';
			}
			return m_grid[cx, cy];
		}

		public bool IsStation(int cx, int cy)
		{
			return m_stationCells.Contains(Key(cx, cy));
		}

		public bool IsWall(int cx, int cy)
		{
			if (At(cx, cy) == '#')
			{
				return !IsStation(cx, cy);
			}
			return false;
		}

		public bool IsWallVisual(int cx, int cy)
		{
			return At(cx, cy) == '#';
		}

		public bool FitsNear(int cx, int cy)
		{
			for (int i = -1; i <= 1; i++)
			{
				for (int j = -1; j <= 0; j++)
				{
					if (Fits(cx + i, cy + j))
					{
						return true;
					}
				}
			}
			return false;
		}

		public Vector2 CellMin(int cx, int cy)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			return new Vector2(-136f + (float)cx * 8f, -64f + (float)cy * 8f);
		}

		public Vector2 CellCenter(int cx, int cy)
		{
			//IL_0003: 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_0017: Unknown result type (might be due to invalid IL or missing references)
			return CellMin(cx, cy) + new Vector2(4f, 4f);
		}

		public void CellOf(Vector2 local, out int cx, out int cy)
		{
			//IL_0001: 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)
			cx = Mathf.FloorToInt((local.x - -136f) / 8f);
			cy = Mathf.FloorToInt((local.y - -64f) / 8f);
		}

		public List<CellRect> WallRects()
		{
			bool[,] used = new bool[Cols, Rows];
			List<CellRect> list = new List<CellRect>();
			for (int cy = Rows - 1; cy >= 0; cy--)
			{
				for (int i = 0; i < Cols; i++)
				{
					if (used[i, cy] || !IsWall(i, cy))
					{
						continue;
					}
					int j;
					for (j = 1; i + j < Cols && IsWall(i + j, cy) && !used[i + j, cy]; j++)
					{
					}
					int h;
					for (h = 1; cy - h >= 0 && Enumerable.Range(i, j).All((int x) => IsWall(x, cy - h) && !used[x, cy - h]); h++)
					{
					}
					for (int num = i; num < i + j; num++)
					{
						for (int num2 = cy - h + 1; num2 <= cy; num2++)
						{
							used[num, num2] = true;
						}
					}
					list.Add(new CellRect(i, cy - h + 1, j, h));
				}
			}
			return list;
		}

		public List<GateSpec> Gates()
		{
			List<GateSpec> list = new List<GateSpec>();
			HashSet<long> hashSet = new HashSet<long>();
			for (int i = 0; i < Rows; i++)
			{
				for (int j = 0; j < Cols; j++)
				{
					char c = At(j, i);
					if ((c != 'H' && c != 'V') || hashSet.Contains(Key(j, i)))
					{
						continue;
					}
					GateSpec gateSpec = new GateSpec
					{
						Horizontal = (c == 'H'),
						Cx = j,
						Cy = i,
						Length = 0
					};
					if (gateSpec.Horizontal)
					{
						while (At(j + gateSpec.Length, i) == 'H')
						{
							hashSet.Add(Key(j + gateSpec.Length, i));
							gateSpec.Length++;
						}
					}
					else
					{
						while (At(j, i + gateSpec.Length) == 'V')
						{
							hashSet.Add(Key(j, i + gateSpec.Length));
							gateSpec.Length++;
						}
					}
					list.Add(gateSpec);
				}
			}
			return (from g in list
				orderby (!g.Horizontal) ? 1 : 0, g.Cx
				select g).ToList();
		}

		public void SetGateClosed(int index, bool closed)
		{
			if (m_gateCache == null)
			{
				m_gateCache = Gates();
				m_gateClosed = new bool[m_gateCache.Count];
			}
			if (index >= 0 && index < m_gateClosed.Length)
			{
				m_gateClosed[index] = closed;
			}
		}

		private bool GateCellClosed(int cx, int cy)
		{
			if (m_gateCache == null)
			{
				return false;
			}
			for (int i = 0; i < m_gateCache.Count; i++)
			{
				GateSpec gateSpec = m_gateCache[i];
				bool num;
				if (!gateSpec.Horizontal)
				{
					if (cx != gateSpec.Cx || cy < gateSpec.Cy)
					{
						continue;
					}
					num = cy < gateSpec.Cy + gateSpec.Length;
				}
				else
				{
					if (cy != gateSpec.Cy || cx < gateSpec.Cx)
					{
						continue;
					}
					num = cx < gateSpec.Cx + gateSpec.Length;
				}
				if (num)
				{
					return m_gateClosed[i];
				}
			}
			return false;
		}

		private bool Walkable(int cx, int cy)
		{
			switch (At(cx, cy))
			{
			case '.':
			case 'A':
			case 'E':
				return true;
			case 'H':
			case 'V':
				return !GateCellClosed(cx, cy);
			default:
				return false;
			}
		}

		public bool Fits(int cx, int cy)
		{
			for (int i = cx - 1; i <= cx + 1; i++)
			{
				for (int j = cy; j <= cy + 1; j++)
				{
					if (!Walkable(i, j))
					{
						return false;
					}
				}
			}
			return true;
		}

		public bool NextStep(Vector2 from, Vector2 goal, out Vector2 step, out bool reachesGoal)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_0218: Unknown result type (might be due to invalid IL or missing references)
			//IL_021d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: Unknown result type (might be due to invalid IL or missing references)
			//IL_032d: Unknown result type (might be due to invalid IL or missing references)
			//IL_034a: Unknown result type (might be due to invalid IL or missing references)
			//IL_039c: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_0367: 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)
			//IL_0417: Unknown result type (might be due to invalid IL or missing references)
			//IL_041c: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_03be: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03cb: 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)
			step = from;
			reachesGoal = false;
			CellOf(from, out var cx, out var cy);
			if (!Fits(cx, cy))
			{
				Dictionary<long, long> dictionary = new Dictionary<long, long>();
				Queue<int[]> queue = new Queue<int[]>();
				for (int i = -1; i <= 1; i++)
				{
					for (int j = -1; j <= 1; j++)
					{
						if (Walkable(cx + i, cy + j) && !dictionary.ContainsKey(Key(cx + i, cy + j)))
						{
							dictionary[Key(cx + i, cy + j)] = -1L;
							queue.Enqueue(new int[2]
							{
								cx + i,
								cy + j
							});
						}
					}
				}
				while (queue.Count > 0)
				{
					int[] array = queue.Dequeue();
					if (Fits(array[0], array[1]))
					{
						long num = Key(array[0], array[1]);
						while (dictionary[num] != -1 && dictionary[dictionary[num]] != -1)
						{
							num = dictionary[num];
						}
						step = CellCenter((int)(num >> 32), (int)num);
						return true;
					}
					for (int k = 0; k < 4; k++)
					{
						int num2 = array[0] + DX[k];
						int num3 = array[1] + DY[k];
						long key = Key(num2, num3);
						if (!dictionary.ContainsKey(key) && Walkable(num2, num3))
						{
							dictionary[key] = Key(array[0], array[1]);
							queue.Enqueue(new int[2] { num2, num3 });
						}
					}
				}
				return false;
			}
			CellOf(goal, out var cx2, out var cy2);
			Dictionary<long, long> dictionary2 = new Dictionary<long, long>();
			Queue<int[]> queue2 = new Queue<int[]>();
			List<int[]> list = new List<int[]>();
			queue2.Enqueue(new int[2] { cx, cy });
			dictionary2[Key(cx, cy)] = -1L;
			int num4 = cx;
			int num5 = cy;
			Vector2 val = CellCenter(cx, cy) - goal;
			float num6 = ((Vector2)(ref val)).sqrMagnitude;
			while (queue2.Count > 0)
			{
				int[] array2 = queue2.Dequeue();
				list.Add(array2);
				val = CellCenter(array2[0], array2[1]) - goal;
				float sqrMagnitude = ((Vector2)(ref val)).sqrMagnitude;
				if (sqrMagnitude < num6)
				{
					num6 = sqrMagnitude;
					num4 = array2[0];
					num5 = array2[1];
				}
				for (int l = 0; l < 4; l++)
				{
					int num7 = array2[0] + DX[l];
					int num8 = array2[1] + DY[l];
					long key2 = Key(num7, num8);
					if (!dictionary2.ContainsKey(key2) && Fits(num7, num8))
					{
						dictionary2[key2] = Key(array2[0], array2[1]);
						queue2.Enqueue(new int[2] { num7, num8 });
					}
				}
			}
			reachesGoal = Mathf.Abs(num4 - cx2) <= 1 && Mathf.Abs(num5 - cy2) <= 1;
			if (!reachesGoal)
			{
				int[] array3 = Best(list, goal, (int[] c) => CanSwingFrom(c, goal)) ?? Best(list, goal, (int[] c) => LaneOpen(CellCenter(c[0], c[1]), goal)) ?? Best(list, goal, (int[] c) => !InHeroReach(CellCenter(c[0], c[1]), goal));
				if (array3 != null)
				{
					num4 = array3[0];
					num5 = array3[1];
				}
			}
			if (num4 == cx && num5 == cy)
			{
				Vector2 val2 = CellCenter(cx, cy);
				val = val2 - from;
				if (((Vector2)(ref val)).sqrMagnitude > 2.25f)
				{
					step = val2;
					return true;
				}
				step = (reachesGoal ? goal : val2);
				return reachesGoal;
			}
			long num9 = Key(num4, num5);
			long num10 = Key(cx, cy);
			while (dictionary2[num9] != num10)
			{
				num9 = dictionary2[num9];
			}
			step = CellCenter((int)(num9 >> 32), (int)num9);
			return true;
		}

		private static int[] Best(List<int[]> cells, Vector2 goal, Func<int[], bool> ok)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			int[] result = null;
			float num = float.MaxValue;
			foreach (int[] cell in cells)
			{
				Vector2 val = new Vector2(-136f + (float)cell[0] * 8f + 4f, -64f + (float)cell[1] * 8f + 4f) - goal;
				float sqrMagnitude = ((Vector2)(ref val)).sqrMagnitude;
				if (sqrMagnitude < num && ok(cell))
				{
					num = sqrMagnitude;
					result = cell;
				}
			}
			return result;
		}

		private bool BlocksSight(int cx, int cy)
		{
			switch (At(cx, cy))
			{
			case 'H':
			case 'V':
				return GateCellClosed(cx, cy);
			default:
				return false;
			case '#':
				return true;
			}
		}

		private bool SightClear(Vector2 a, Vector2 b)
		{
			//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_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: 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)
			Vector2 val = b - a;
			int num = Mathf.Max(1, Mathf.CeilToInt(((Vector2)(ref val)).magnitude));
			for (int i = 1; i < num; i++)
			{
				CellOf(a + val * ((float)i / (float)num), out var cx, out var cy);
				if (BlocksSight(cx, cy))
				{
					return false;
				}
			}
			return true;
		}

		private bool CanSwingFrom(int[] c, Vector2 goal)
		{
			//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_000d: 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_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: 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_0063: 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_0073: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val = CellCenter(c[0], c[1]);
			Vector2 val2 = val + new Vector2(0f, 10f) - (goal + new Vector2(0f, 8f));
			if (((Vector2)(ref val2)).magnitude > 18f)
			{
				return false;
			}
			return SightClear(val + new Vector2(0f, 2.5f), goal + new Vector2(0f, 0.5f));
		}

		private bool LaneOpen(Vector2 from, Vector2 goal)
		{
			//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_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: 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_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val = goal - from;
			int num = Mathf.Max(1, Mathf.CeilToInt(((Vector2)(ref val)).magnitude / 2f));
			for (int i = 1; i <= num; i++)
			{
				CellOf(from + val * ((float)i / (float)num), out var cx, out var cy);
				if (BlocksSight(cx - 1, cy) || BlocksSight(cx, cy) || BlocksSight(cx + 1, cy))
				{
					return false;
				}
			}
			return true;
		}

		private static bool InHeroReach(Vector2 pivot, Vector2 goal)
		{
			//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_0012: 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)
			float num = Mathf.Abs(goal.x - pivot.x);
			float num2 = goal.y - pivot.y;
			if (num < 25f && num2 > -15f)
			{
				return num2 < 60f;
			}
			return false;
		}

		public Vector3 World(Room room, Vector2 local)
		{
			//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_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			Vector3 position = ((Component)room).transform.position;
			return new Vector3(position.x + local.x, position.y + local.y, 0f);
		}

		public Built Build(Room room)
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Expected O, but got Unknown
			//IL_00a2: 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_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: 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_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: 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_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0225: Unknown result type (might be due to invalid IL or missing references)
			//IL_026a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0277: Unknown result type (might be due to invalid IL or missing references)
			Built built = new Built
			{
				Room = room
			};
			bool hidden = ((Component)room).gameObject.layer == 12;
			Vector2 val2 = default(Vector2);
			foreach (CellRect item in WallRects())
			{
				Vector2 val = CellMin(item.x, item.y);
				((Vector2)(ref val2))..ctor((float)item.width * 8f, (float)item.height * 8f);
				GameObject val3 = new GameObject("LabyWall");
				val3.layer = 9;
				val3.transform.SetParent(((Component)room).transform, false);
				val3.transform.position = World(room, val + val2 * 0.5f);
				val3.AddComponent<BoxCollider>().size = new Vector3(val2.x, val2.y, 50f);
				Vector3 val4 = World(room, val);
				room.AddPropRect(new Rect(val4.x, val4.y, val2.x, val2.y));
				built.Walls.Add(val3);
			}
			exAtlas atlas = Templates.EnvSheet.Atlas;
			int[] array = Templates.EnvSheet.Frames("top");
			int[] array2 = Templates.EnvSheet.Frames("face");
			for (int i = 0; i < Rows; i++)
			{
				for (int j = 0; j < Cols; j++)
				{
					if (IsWallVisual(j, i))
					{
						int num = (j * 7 + i * 13) & 1;
						int num2 = (int)((IsWallVisual(j, i + 1) ? 1u : 0u) | (uint)(IsWallVisual(j + 1, i) ? 2 : 0) | (uint)(IsWallVisual(j, i - 1) ? 4 : 0)) | (IsWallVisual(j - 1, i) ? 8 : 0);
						Vector3 world = World(room, CellMin(j, i) + new Vector2(4f, 0f));
						GameObject val5 = MakeSprite(room, "LabyWallTop", world, atlas, array[num * 16 + num2], new Vector2(0f, 10f), hidden);
						if (!IsWallVisual(j, i - 1))
						{
							int num3 = (HasFace(j - 1, i) ? 1 : 0) + (HasFace(j + 1, i) ? 2 : 0);
							MakeSprite(room, "LabyWallFace", world, atlas, array2[num * 4 + num3], Vector2.zero, hidden).transform.SetParent(val5.transform, true);
						}
					}
				}
			}
			List<GateSpec> list = Gates();
			for (int k = 0; k < list.Count; k++)
			{
				built.Gates.Add(Gate.Create(this, room, k, list[k], hidden));
			}
			return built;
		}

		private bool HasFace(int cx, int cy)
		{
			if (IsWallVisual(cx, cy))
			{
				return !IsWallVisual(cx, cy - 1);
			}
			return false;
		}

		public static GameObject MakeSprite(Room room, string name, Vector3 world, exAtlas atlas, int index, Vector2 offset, bool hidden)
		{
			//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_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Un

plugins/CrawlCustomBosses/DragonBoss.dll

Decompiled 4 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using BepInEx;
using BossKit;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("DragonBoss")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("DragonBoss")]
[assembly: AssemblyTitle("DragonBoss")]
[assembly: AssemblyVersion("1.0.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 DragonBoss
{
	internal static class IgnisBotPatch
	{
		internal static bool Active;

		private static readonly FieldRef<BotHero, Boss> s_boss = AccessTools.FieldRefAccess<BotHero, Boss>("m_boss");

		private static readonly FieldRef<BotHero, Vector2> s_pathDirection = AccessTools.FieldRefAccess<BotHero, Vector2>("m_pathDirection");

		private static readonly MethodInfo s_seek = AccessTools.Method(typeof(BotHero), "SeekPathTarget", new Type[2]
		{
			typeof(Vector2),
			typeof(bool)
		}, (Type[])null);

		private static readonly MethodInfo s_runSmooth = AccessTools.Method(typeof(BotHero), "RunSmooth", new Type[1] { typeof(Vector2) }, (Type[])null);

		[HarmonyPatch(typeof(BotHero), "UpdateBossFightKourok")]
		[HarmonyPrefix]
		private static bool HideFromFirewash(BotHero __instance, ref bool __result)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: 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_0083: 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_008a: 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_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				IgnisBoss ignisBoss = s_boss.Invoke(__instance) as IgnisBoss;
				if ((Object)(object)ignisBoss == (Object)null || (object)s_seek == null || (object)s_runSmooth == null)
				{
					return true;
				}
				Vector2 val = Vector2.op_Implicit(((Component)__instance).transform.position);
				PlayerMovement component = ((Component)__instance).GetComponent<PlayerMovement>();
				float num = (((Object)(object)component != (Object)null) ? component.GetSpeedMax() : 0f);
				if (!ignisBoss.BotCoverSpot(val, (num > 1f) ? num : 73f, out var world))
				{
					return true;
				}
				Vector2 val2 = Vector2.zero;
				Vector2 val3 = world - val;
				if (((Vector2)(ref val3)).magnitude > 2f)
				{
					s_seek.Invoke(__instance, new object[2] { world, false });
					val2 = s_pathDirection.Invoke(__instance);
				}
				s_runSmooth.Invoke(__instance, new object[1] { val2 });
				__result = true;
				return false;
			}
			catch (Exception ex)
			{
				if (Plugin.Ctx != null)
				{
					Plugin.Ctx.Log.WarnOnce("ignis bot cover", ex);
				}
				return true;
			}
		}
	}
	internal sealed class IgnisFirewash
	{
		private readonly IgnisHoard m_hoard;

		private readonly GameObject[] m_rays;

		private bool m_shown;

		public IgnisFirewash(IgnisHoard hoard)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			m_hoard = hoard;
			m_rays = (GameObject[])(object)new GameObject[31];
			ClipLibrary tiles = Templates.Tiles;
			for (int i = 0; i < m_rays.Length; i++)
			{
				exSprite val = KitArt.CreateSprite(((Component)hoard.Room).transform, tiles.Sheet, "IgnisGlowRay", 0, hoard.World(Vector2.zero), (Anchor)3, false, 0f);
				KitArt.Animate(val, (IEnumerable<exSpriteAnimClip>)null, tiles["IgnisGlowRay"], true);
				m_rays[i] = ((Component)val).gameObject;
				m_rays[i].SetActive(false);
			}
		}

		public static float RayAngle(int i, float aim)
		{
			return aim - 50f + 100f * (float)i / 30f;
		}

		public static Vector2 Dir(float deg)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			float num = deg * ((float)Math.PI / 180f);
			return new Vector2(Mathf.Cos(num), Mathf.Sin(num));
		}

		public float Stop(Vector2 origin, float deg, out Cover cover)
		{
			//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_0007: 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_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val = Dir(deg);
			float num = IgnisHoard.RayToPolygon(origin, val, 160f);
			cover = m_hoard.FirstCover(origin, origin + val * num, out var t);
			if (cover == null)
			{
				return num;
			}
			return num * Mathf.Max(0f, t);
		}

		public void Hide()
		{
			if (!m_shown)
			{
				return;
			}
			m_shown = false;
			GameObject[] rays = m_rays;
			foreach (GameObject val in rays)
			{
				if ((Object)(object)val != (Object)null)
				{
					val.SetActive(false);
				}
			}
		}

		public void Refresh(Vector2 origin, float aim)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_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_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: 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)
			m_shown = true;
			for (int i = 0; i < m_rays.Length; i++)
			{
				GameObject val = m_rays[i];
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				float num = RayAngle(i, aim);
				Cover cover;
				float num2 = Stop(origin, num, out cover) - 26f;
				if (num2 < 1f)
				{
					if (val.activeSelf)
					{
						val.SetActive(false);
					}
					continue;
				}
				if (!val.activeSelf)
				{
					val.SetActive(true);
				}
				Vector3 val2 = m_hoard.World(origin + Dir(num) * 26f);
				val.transform.position = new Vector3(val2.x, val2.y, 50f);
				val.transform.rotation = Quaternion.Euler(0f, 0f, num);
				val.transform.localScale = new Vector3(num2 / 4f, 1f, 1f);
			}
		}

		public int Release(Vector2 origin, float aim, int key, GameObject owner)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: 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_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_004d: 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_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			int num = 0;
			for (int i = 0; i < 31; i++)
			{
				float num2 = RayAngle(i, aim);
				Vector2 val = Dir(num2);
				float num3 = IgnisHoard.RayToPolygon(origin, val, 160f);
				if (num3 <= 4f)
				{
					continue;
				}
				Vector2 local = origin + val * 4f;
				GameObject val2 = KitFx.SpawnOwned(Templates.TongueFx, Vector2.op_Implicit(m_hoard.World(local)), num2, owner, false);
				if (!((Object)(object)val2 == (Object)null))
				{
					IgnisTongue component = val2.GetComponent<IgnisTongue>();
					if ((Object)(object)component != (Object)null)
					{
						component.Init(m_hoard, origin, val, 4f, num3, key);
					}
					num++;
				}
			}
			return num;
		}
	}
	internal sealed class IgnisOneShot : MonoBehaviour
	{
		public float Life;

		public Transform Follow;

		public Vector3 FollowOffset;

		private float m_age;

		private void Update()
		{
			//IL_0026: 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_0043: 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_0059: Unknown result type (might be due to invalid IL or missing references)
			m_age += Time.deltaTime;
			if ((Object)(object)Follow != (Object)null)
			{
				Vector3 val = Follow.position + FollowOffset;
				((Component)this).transform.position = new Vector3(val.x, val.y, ((Component)this).transform.position.z);
			}
			if (m_age >= Life)
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
			}
		}
	}
	internal static class IgnisFx
	{
		public static GameObject OneShot(Transform parent, string clip, Vector2 world, float heightOffset, Anchor anchor, Transform follow = null)
		{
			//IL_0022: 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_0033: 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_0084: 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_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: 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)
			try
			{
				ClipLibrary env = Templates.Env;
				if (env == null || !env.Has(clip))
				{
					return null;
				}
				exSprite obj = KitArt.CreateSprite(parent, env.Sheet, clip, 0, new Vector3(world.x, world.y, 0f), anchor, true, heightOffset);
				exSpriteAnimClip val = env[clip];
				KitArt.Animate(obj, (IEnumerable<exSpriteAnimClip>)null, val, true);
				IgnisOneShot ignisOneShot = ((Component)obj).gameObject.AddComponent<IgnisOneShot>();
				ignisOneShot.Life = val.length + 0.02f;
				if ((Object)(object)follow != (Object)null)
				{
					ignisOneShot.Follow = follow;
					ignisOneShot.FollowOffset = new Vector3(world.x - follow.position.x, world.y - follow.position.y, 0f);
				}
				return ((Component)obj).gameObject;
			}
			catch (Exception ex)
			{
				if (Plugin.Ctx != null)
				{
					Plugin.Ctx.Log.WarnOnce("oneshot " + clip, ex);
				}
				return null;
			}
		}
	}
	internal enum CoverKind
	{
		Heap,
		Mound,
		Mimic
	}
	internal sealed class Cover
	{
		public CoverKind Kind;

		public IgnisMound Mound;

		public IgnisMimic Mimic;

		public Rect Static;

		public bool Active
		{
			get
			{
				switch (Kind)
				{
				case CoverKind.Mound:
					if (Mound != null)
					{
						return Mound.StopsFire;
					}
					return false;
				case CoverKind.Mimic:
					if ((Object)(object)Mimic != (Object)null)
					{
						return Mimic.IsCover;
					}
					return false;
				default:
					return true;
				}
			}
		}

		public Rect Box => (Rect)(Kind switch
		{
			CoverKind.Mound => Mound.Box, 
			CoverKind.Mimic => Mimic.CoverBoxLocal, 
			_ => Static, 
		});
	}
	internal sealed class IgnisHoard
	{
		private sealed class Puff
		{
			public GameObject Go;

			public Vector2 Last;

			public int Key;
		}

		public readonly IgnisBoss Boss;

		public readonly Room Room;

		public readonly List<IgnisMound> Mounds = new List<IgnisMound>();

		public readonly List<Cover> Covers = new List<Cover>();

		public readonly List<IgnisMimic> Mimics = new List<IgnisMimic>();

		private exSpriteAnimation m_heapAnim;

		private readonly bool[] m_spillUsed;

		private float m_regrowAt;

		private int m_key;

		private readonly List<Puff> m_puffs = new List<Puff>();

		private readonly List<IgnisBoulder> m_boulders = new List<IgnisBoulder>();

		private float m_heapRattleEnd = -1f;

		public int Version { get; private set; }

		public float Now => ((KitBoss)Boss).UnpausedTime;

		public event Action<IgnisMound> PoolFormed;

		public IgnisHoard(IgnisBoss boss, Room room)
		{
			Boss = boss;
			Room = room;
			m_spillUsed = new bool[Layout.Spills.Length];
		}

		public int NextKey()
		{
			return ++m_key;
		}

		public void Touch()
		{
			Version++;
		}

		public Vector3 World(Vector2 local)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			return ((KitBoss)Boss).World(local);
		}

		public Vector2 Local(Vector3 world)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			return ((KitBoss)Boss).RoomLocal(world);
		}

		public void Build()
		{
			//IL_000c: 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_005d: 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_00b4: 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)
			BuildOverlays();
			KitRoom.AddWall(Room, Layout.Heap, "IgnisHeapWall", 22, true);
			Covers.Add(new Cover
			{
				Kind = CoverKind.Heap,
				Static = Layout.Heap
			});
			exSprite val = KitArt.CreateSprite(((Component)Room).transform, Templates.Env.Sheet, "IgnisHeap", 0, World(Layout.HeapSprite), (Anchor)7, true, 0f);
			m_heapAnim = KitArt.Animate(val, (IEnumerable<exSpriteAnimClip>)(object)new exSpriteAnimClip[1] { Templates.Env["IgnisHeapRattle"] }, Templates.Env["IgnisHeap"], true);
			for (int i = 0; i < Layout.Mounds.Length; i++)
			{
				AddMound(new IgnisMound(this, Layout.Mounds[i], "M" + (i + 1), inert: false, spill: false, -1));
			}
			if ((Object)(object)Templates.MimicTemplate == (Object)null)
			{
				for (int j = 0; j < Layout.Mimics.Length; j++)
				{
					AddMound(new IgnisMound(this, Layout.Mimics[j], "X" + (j + 1), inert: true, spill: false, -1));
				}
			}
			m_regrowAt = float.MaxValue;
		}

		private void BuildOverlays()
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: 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_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				exSprite obj = KitArt.CreateSprite(((Component)Room).transform, Templates.Tiles.Sheet, "IgnisFloorCave", 0, World(Vector2.zero), (Anchor)4, false, 0f);
				Vector3 position = ((Component)obj).transform.position;
				((Component)obj).transform.position = new Vector3(position.x, position.y, 99f);
				exSprite obj2 = KitArt.CreateSprite(((Component)Room).transform, Templates.Tiles.Sheet, "IgnisBackWall", 0, World(Layout.BackWall), (Anchor)6, false, 0f);
				position = ((Component)obj2).transform.position;
				((Component)obj2).transform.position = new Vector3(position.x, position.y, 70f);
			}
			catch (Exception ex)
			{
				((KitBoss)Boss).Ctx.Log.WarnOnce("ignis overlays", "the cave overlays failed, the vanilla floor shows: " + ex.Message);
			}
		}

		private void AddMound(IgnisMound m)
		{
			Mounds.Add(m);
			Covers.Add(new Cover
			{
				Kind = CoverKind.Mound,
				Mound = m
			});
			Touch();
		}

		public void AddInert(Vector2 centre, string name)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			AddMound(new IgnisMound(this, centre, name, inert: true, spill: false, -1));
		}

		public void AddMimic(IgnisMimic mimic)
		{
			Mimics.Add(mimic);
			Covers.Add(new Cover
			{
				Kind = CoverKind.Mimic,
				Mimic = mimic
			});
		}

		public void StartRegrowth()
		{
			m_regrowAt = Now + 20f;
		}

		public static float SegmentBox(Vector2 a, Vector2 b, Rect r)
		{
			//IL_000c: 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_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: 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_0035: 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_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			float num = 0f;
			float num2 = 1f;
			float num3 = b.x - a.x;
			float num4 = b.y - a.y;
			if (Mathf.Abs(num3) < 1E-09f)
			{
				if (a.x < ((Rect)(ref r)).xMin || a.x > ((Rect)(ref r)).xMax)
				{
					return -1f;
				}
			}
			else
			{
				float num5 = (((Rect)(ref r)).xMin - a.x) / num3;
				float num6 = (((Rect)(ref r)).xMax - a.x) / num3;
				if (num5 > num6)
				{
					float num7 = num5;
					num5 = num6;
					num6 = num7;
				}
				num = Mathf.Max(num, num5);
				num2 = Mathf.Min(num2, num6);
				if (num > num2)
				{
					return -1f;
				}
			}
			if (Mathf.Abs(num4) < 1E-09f)
			{
				if (a.y < ((Rect)(ref r)).yMin || a.y > ((Rect)(ref r)).yMax)
				{
					return -1f;
				}
			}
			else
			{
				float num8 = (((Rect)(ref r)).yMin - a.y) / num4;
				float num9 = (((Rect)(ref r)).yMax - a.y) / num4;
				if (num8 > num9)
				{
					float num10 = num8;
					num8 = num9;
					num9 = num10;
				}
				num = Mathf.Max(num, num8);
				num2 = Mathf.Min(num2, num9);
				if (num > num2)
				{
					return -1f;
				}
			}
			return num;
		}

		public Cover FirstCover(Vector2 a, Vector2 b, out float t)
		{
			//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)
			return FirstCover(a, b, skipAroundStart: false, out t);
		}

		public Cover FirstCover(Vector2 a, Vector2 b, bool skipAroundStart, out float t)
		{
			//IL_0024: 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_0036: 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_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			t = -1f;
			Cover cover = null;
			for (int i = 0; i < Covers.Count; i++)
			{
				Cover cover2 = Covers[i];
				if (!cover2.Active)
				{
					continue;
				}
				Rect box = cover2.Box;
				if (!skipAroundStart || !InBox(a, box))
				{
					float num = SegmentBox(a, b, box);
					if (num >= 0f && (cover == null || num < t))
					{
						cover = cover2;
						t = num;
					}
				}
			}
			return cover;
		}

		public static bool InBox(Vector2 p, Rect r)
		{
			//IL_0000: 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_002a: 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)
			if (p.x >= ((Rect)(ref r)).xMin - 0.01f && p.x <= ((Rect)(ref r)).xMax + 0.01f && p.y >= ((Rect)(ref r)).yMin - 0.01f)
			{
				return p.y <= ((Rect)(ref r)).yMax + 0.01f;
			}
			return false;
		}

		public bool InsideCover(Vector2 p)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < Covers.Count; i++)
			{
				Cover cover = Covers[i];
				if (cover.Active && InBox(p, cover.Box))
				{
					return true;
				}
			}
			return false;
		}

		public static float RayToPolygon(Vector2 origin, Vector2 dir, float max)
		{
			//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)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: 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_003a: 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_005a: 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)
			//IL_0062: 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_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: 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_0094: 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)
			float num = max;
			Vector2[] polygon = Layout.Polygon;
			for (int i = 0; i < polygon.Length; i++)
			{
				Vector2 val = polygon[i];
				Vector2 val2 = polygon[(i + 1) % polygon.Length] - val;
				float num2 = dir.x * val2.y - dir.y * val2.x;
				if (!(Mathf.Abs(num2) < 1E-06f))
				{
					Vector2 val3 = val - origin;
					float num3 = (val3.x * val2.y - val3.y * val2.x) / num2;
					float num4 = (val3.x * dir.y - val3.y * dir.x) / num2;
					if (num3 >= 0f && num4 >= 0f && num4 <= 1f && num3 < num)
					{
						num = num3;
					}
				}
			}
			return num;
		}

		public void FireStop(Cover c, int key)
		{
			if (c != null && c.Kind == CoverKind.Mound)
			{
				c.Mound.Heat(key);
			}
		}

		public void PhaseHeat()
		{
			int key = NextKey();
			IgnisMound[] array = Mounds.ToArray();
			for (int i = 0; i < array.Length; i++)
			{
				array[i].Heat(key);
			}
		}

		public void Rattle()
		{
			if ((Object)(object)m_heapAnim != (Object)null)
			{
				try
				{
					m_heapAnim.Play(Templates.Env["IgnisHeapRattle"]);
					m_heapRattleEnd = Now + Templates.Env.Length("IgnisHeapRattle") * 3f;
				}
				catch (Exception ex)
				{
					((KitBoss)Boss).Ctx.Log.WarnOnce("heap rattle", ex);
				}
			}
		}

		internal void OnPool(IgnisMound m)
		{
			Touch();
			IgnisNotes.Note("pool formed at " + m.Name);
			this.PoolFormed?.Invoke(m);
		}

		public IgnisMound NewestLivePool()
		{
			IgnisMound ignisMound = null;
			foreach (IgnisMound mound in Mounds)
			{
				if (mound.IsLivePool && (ignisMound == null || mound.PoolBorn > ignisMound.PoolBorn))
				{
					ignisMound = mound;
				}
			}
			return ignisMound;
		}

		public int StandingCount()
		{
			int num = 0;
			foreach (IgnisMound mound in Mounds)
			{
				if (mound.CountsStanding)
				{
					num++;
				}
			}
			return num;
		}

		public bool SpillFree(int i)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: 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_00da: 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_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: 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_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			if (m_spillUsed[i])
			{
				return false;
			}
			Rect val = MoundBox(Layout.Spills[i]);
			foreach (Cover cover in Covers)
			{
				if (cover.Kind != CoverKind.Heap && cover.Active && Gap(val, cover.Box) < 13.999f)
				{
					return false;
				}
			}
			foreach (IgnisMound mound in Mounds)
			{
				if (mound.State != IgnisMound.S.Gone && mound.State != IgnisMound.S.Standing && Gap(val, mound.PoolBox) < 1f)
				{
					return false;
				}
			}
			Rect val2 = val;
			Vector3 val3 = World(((Rect)(ref val2)).center);
			return KitGeom.BoxFree(new Rect(val3.x - ((Rect)(ref val2)).width * 0.5f, val3.y - ((Rect)(ref val2)).height * 0.5f, ((Rect)(ref val2)).width, ((Rect)(ref val2)).height), 98304);
		}

		public int Spill(int n)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			int num = 0;
			for (int i = 0; i < Layout.Spills.Length; i++)
			{
				if (num >= n)
				{
					break;
				}
				if (SpillFree(i))
				{
					m_spillUsed[i] = true;
					IgnisMound m = new IgnisMound(this, Layout.Spills[i], "S" + (i + 1), inert: false, spill: true, i);
					AddMound(m);
					num++;
				}
			}
			if (num > 0)
			{
				IgnisCues.Play("IgnisSpill", ((Component)Boss).transform);
				Rattle();
				IgnisNotes.Note(num + " cold mound(s) spilled");
			}
			return num;
		}

		internal void ReleaseSpill(int index)
		{
			if (index >= 0 && index < m_spillUsed.Length)
			{
				m_spillUsed[index] = false;
			}
		}

		public void TrackPuff(GameObject puff, int key)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)puff == (Object)null))
			{
				m_puffs.Add(new Puff
				{
					Go = puff,
					Last = Local(puff.transform.position),
					Key = key
				});
			}
		}

		public void TrackBoulder(IgnisBoulder b)
		{
			if ((Object)(object)b != (Object)null && !m_boulders.Contains(b))
			{
				m_boulders.Add(b);
			}
		}

		public void Step(float dt, bool fighting)
		{
			float now = Now;
			for (int num = Mounds.Count - 1; num >= 0; num--)
			{
				Mounds[num].Step(dt, now);
			}
			if (m_heapRattleEnd > 0f && now >= m_heapRattleEnd && (Object)(object)m_heapAnim != (Object)null)
			{
				m_heapRattleEnd = -1f;
				m_heapAnim.Play(Templates.Env["IgnisHeap"]);
			}
			StepPuffs();
			if (fighting && now >= m_regrowAt)
			{
				m_regrowAt = now + 20f;
				if (StandingCount() < 4)
				{
					Spill(1);
				}
			}
		}

		private void StepPuffs()
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: 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_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: 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_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: 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_009c: 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)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			for (int num = m_puffs.Count - 1; num >= 0; num--)
			{
				Puff puff = m_puffs[num];
				if ((Object)(object)puff.Go == (Object)null || !puff.Go.activeInHierarchy)
				{
					m_puffs.RemoveAt(num);
				}
				else
				{
					Vector2 val = Local(puff.Go.transform.position);
					float t;
					Cover cover = FirstCover(puff.Last, val, out t);
					if (cover != null)
					{
						FireStop(cover, puff.Key);
						Vector2 local = puff.Last + (val - puff.Last) * t;
						IgnisFx.OneShot(((Component)Room).transform, "IgnisGoldSpatter", Vector2.op_Implicit(World(local)), 0f, (Anchor)7);
						m_puffs.RemoveAt(num);
						try
						{
							puff.Go.SendMessage("MsgSpawnOnDestroy", (SendMessageOptions)1);
							ExtentionsMethodsPool.Despawn(puff.Go);
						}
						catch (Exception ex)
						{
							((KitBoss)Boss).Ctx.Log.WarnOnce("puff stop", ex);
						}
					}
					else
					{
						puff.Last = val;
					}
				}
			}
			for (int num2 = m_boulders.Count - 1; num2 >= 0; num2--)
			{
				if ((Object)(object)m_boulders[num2] == (Object)null || !((Component)m_boulders[num2]).gameObject.activeInHierarchy)
				{
					m_boulders.RemoveAt(num2);
				}
			}
		}

		public void StopAll()
		{
			foreach (IgnisMound mound in Mounds)
			{
				mound.StopDamage();
			}
			m_regrowAt = float.MaxValue;
		}

		public static Rect MoundBox(Vector2 c)
		{
			//IL_0000: 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_0022: Unknown result type (might be due to invalid IL or missing references)
			return new Rect(c.x - 13f, c.y - 8f, 26f, 16f);
		}

		public static Rect PoolRect(Vector2 c)
		{
			//IL_0000: 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_0022: Unknown result type (might be due to invalid IL or missing references)
			return new Rect(c.x - 17f, c.y - 7f, 34f, 14f);
		}

		public static float Gap(Rect a, Rect b)
		{
			float num = Mathf.Max(0f, Mathf.Max(((Rect)(ref a)).xMin, ((Rect)(ref b)).xMin) - Mathf.Min(((Rect)(ref a)).xMax, ((Rect)(ref b)).xMax));
			float num2 = Mathf.Max(0f, Mathf.Max(((Rect)(ref a)).yMin, ((Rect)(ref b)).yMin) - Mathf.Min(((Rect)(ref a)).yMax, ((Rect)(ref b)).yMax));
			return Mathf.Sqrt(num * num + num2 * num2);
		}

		public void SolidBoxes(List<Rect> into)
		{
			//IL_0029: 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_008d: Unknown result type (might be due to invalid IL or missing references)
			into.Clear();
			foreach (Cover cover in Covers)
			{
				if (cover.Kind == CoverKind.Heap)
				{
					into.Add(cover.Static);
				}
				else if (cover.Kind == CoverKind.Mound)
				{
					if (cover.Mound.Solid)
					{
						into.Add(cover.Mound.Box);
					}
				}
				else if ((Object)(object)cover.Mimic != (Object)null && cover.Mimic.Alive && !cover.Mimic.Inhabited)
				{
					into.Add(cover.Mimic.CoverBoxLocal);
				}
			}
		}
	}
	internal sealed class IgnisMound
	{
		public enum S
		{
			Spilling,
			Standing,
			Slump,
			Pool,
			PoolDull,
			Crust,
			CrustFade,
			Draining,
			Smashing,
			Gone
		}

		private static readonly string[] HeatClips = new string[4] { "IgnisMoundHeat0", "IgnisMoundHeat1", "IgnisMoundHeat2", "IgnisMoundHeat3" };

		private static readonly string[] HeatCues = new string[4] { null, "IgnisMoundHeat1", "IgnisMoundHeat2", "IgnisMoundHeat3" };

		public readonly string Name;

		public readonly Vector2 Centre;

		public readonly bool Inert;

		public readonly bool IsSpill;

		private readonly IgnisHoard m_hoard;

		private readonly int m_spillIndex;

		private GameObject m_blocker;

		private bool m_solid;

		private GameObject m_stand;

		private GameObject m_floor;

		private exSpriteAnimation m_standAnim;

		private exSpriteAnimation m_floorAnim;

		private GameObject m_pool;

		private DamageEffect m_poolDamage;

		private bool m_poolOn;

		private float m_timer;

		private float m_lastFire;

		private readonly List<int> m_keys = new List<int>();

		public S State { get; private set; }

		public int HeatStep { get; private set; }

		public float PoolBorn { get; private set; }

		public Rect Box => IgnisHoard.MoundBox(Centre);

		public Rect PoolBox => IgnisHoard.PoolRect(Centre);

		public bool StopsFire
		{
			get
			{
				if (State != S.Standing)
				{
					return State == S.Slump;
				}
				return true;
			}
		}

		public bool Solid => m_solid;

		public bool IsLivePool => State == S.Pool;

		public bool CountsStanding
		{
			get
			{
				if (!Inert)
				{
					if (State != S.Standing && State != S.Slump)
					{
						return State == S.Spilling;
					}
					return true;
				}
				return false;
			}
		}

		public IgnisMound(IgnisHoard hoard, Vector2 centre, string name, bool inert, bool spill, int spillIndex)
		{
			//IL_0019: 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_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//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_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: 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_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_024b: Unknown result type (might be due to invalid IL or missing references)
			//IL_024c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0251: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: 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_0284: Unknown result type (might be due to invalid IL or missing references)
			m_hoard = hoard;
			Centre = centre;
			Name = name;
			Inert = inert;
			IsSpill = spill;
			m_spillIndex = spillIndex;
			Room room = hoard.Room;
			ClipLibrary env = Templates.Env;
			Vector3 val = hoard.World(new Vector2(centre.x, centre.y - 8.5f));
			exSprite val2 = KitArt.CreateSprite(((Component)room).transform, env.Sheet, spill ? "IgnisMoundSpill" : "IgnisMoundHeat0", 0, val, (Anchor)7, true, 8.5f);
			m_stand = ((Component)val2).gameObject;
			m_standAnim = KitArt.Animate(val2, (IEnumerable<exSpriteAnimClip>)(object)new exSpriteAnimClip[6]
			{
				env["IgnisMoundHeat1"],
				env["IgnisMoundHeat2"],
				env["IgnisMoundHeat3"],
				env["IgnisMoundSlump"],
				env["IgnisMoundSmash"],
				env["IgnisMoundSpill"]
			}, env["IgnisMoundHeat0"], !spill);
			exSprite val3 = KitArt.CreateSprite(((Component)room).transform, env.Sheet, "IgnisMoundPool", 0, val, (Anchor)7, false, 0f);
			((Component)val3).transform.position = new Vector3(((Component)val3).transform.position.x, ((Component)val3).transform.position.y, 50f);
			m_floor = ((Component)val3).gameObject;
			m_floorAnim = KitArt.Animate(val3, (IEnumerable<exSpriteAnimClip>)(object)new exSpriteAnimClip[4]
			{
				env["IgnisMoundPoolDull"],
				env["IgnisMoundCrust"],
				env["IgnisMoundCrustFade"],
				env["IgnisMoundDrain"]
			}, env["IgnisMoundPool"], false);
			m_floor.SetActive(false);
			m_blocker = KitRoom.AddWall(room, Box, "IgnisMound" + name, 22, !spill);
			m_lastFire = hoard.Now;
			if (spill)
			{
				State = S.Spilling;
				m_timer = 0.5f;
				m_standAnim.Play(env["IgnisMoundSpill"]);
				m_blocker.SetActive(false);
				Vector3 val4 = hoard.World(centre);
				Rect val5 = default(Rect);
				((Rect)(ref val5))..ctor(val4.x - 13f, val4.y - 8f, 26f, 16f);
				((MonoBehaviour)hoard.Boss).StartCoroutine(KitRoom.WaitUntilClear(val5, 3f, (Action)delegate
				{
					if (State != S.Gone && State != S.Smashing && State != S.Pool && State != S.PoolDull && State != S.Crust && State != S.CrustFade && State != S.Draining)
					{
						SetSolid(on: true);
					}
				}));
			}
			else
			{
				State = S.Standing;
				m_solid = true;
			}
		}

		private void SetSolid(bool on)
		{
			if (!((Object)(object)m_blocker == (Object)null) && m_solid != on)
			{
				m_solid = on;
				KitRoom.SetSolid(m_blocker, on);
				m_hoard.Touch();
			}
		}

		public bool Heat(int key)
		{
			if (Inert || State != S.Standing || m_keys.Contains(key))
			{
				return false;
			}
			m_keys.Add(key);
			if (m_keys.Count > 16)
			{
				m_keys.RemoveAt(0);
			}
			m_lastFire = m_hoard.Now;
			HeatStep++;
			if (HeatStep >= 4)
			{
				BeginSlump();
			}
			else
			{
				Play(m_standAnim, HeatClips[HeatStep]);
				IgnisCues.Play(HeatCues[HeatStep], m_stand.transform);
				IgnisNotes.Note(Name + " heat " + HeatStep);
			}
			return true;
		}

		private void BeginSlump()
		{
			State = S.Slump;
			m_timer = 0.4f;
			Play(m_standAnim, "IgnisMoundSlump");
			IgnisCues.Play("IgnisMoundMelt", m_stand.transform);
			IgnisNotes.Note(Name + " melts");
		}

		private void FormPool()
		{
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			SetSolid(on: false);
			m_stand.SetActive(false);
			m_floor.SetActive(true);
			Play(m_floorAnim, "IgnisMoundPool");
			PoolBorn = m_hoard.Now;
			m_poolOn = false;
			KitBody lifeBody = ((KitBoss)m_hoard.Boss).LifeBody;
			if ((Object)(object)lifeBody != (Object)null && lifeBody.Alive && !((KitBoss)m_hoard.Boss).Won && !((KitBoss)m_hoard.Boss).Killed)
			{
				m_pool = KitFx.SpawnOwned(Templates.PoolFx, Vector2.op_Implicit(m_hoard.World(Centre)), 0f, ((Component)lifeBody).gameObject, false);
				m_poolDamage = (((Object)(object)m_pool != (Object)null) ? m_pool.GetComponent<DamageEffect>() : null);
				if ((Object)(object)m_poolDamage != (Object)null)
				{
					m_poolDamage.AnimDamageOff();
				}
			}
			State = S.Pool;
			m_hoard.OnPool(this);
		}

		public void Take()
		{
			if (State == S.Pool)
			{
				StopDamage();
				State = S.Draining;
				m_timer = 0.67f;
				Play(m_floorAnim, "IgnisMoundDrain");
				IgnisNotes.Note(Name + " pool taken");
			}
		}

		public bool Smash()
		{
			if (Inert || State != S.Standing)
			{
				return false;
			}
			State = S.Smashing;
			m_timer = 0.4f;
			Play(m_standAnim, "IgnisMoundSmash");
			IgnisCues.Play("IgnisMoundSmash", m_stand.transform);
			SetSolid(on: false);
			IgnisNotes.Note(Name + " smashed");
			return true;
		}

		public void StopDamage()
		{
			if ((Object)(object)m_pool != (Object)null)
			{
				try
				{
					if ((Object)(object)m_poolDamage != (Object)null)
					{
						m_poolDamage.AnimDamageOff();
					}
					ExtentionsMethodsPool.Despawn(m_pool);
				}
				catch (Exception ex)
				{
					((KitBoss)m_hoard.Boss).Ctx.Log.WarnOnce("pool despawn", ex);
				}
			}
			m_pool = null;
			m_poolDamage = null;
			m_poolOn = false;
		}

		private static void Play(exSpriteAnimation anim, string clip)
		{
			if ((Object)(object)anim != (Object)null && ((Component)anim).gameObject.activeInHierarchy)
			{
				anim.Play(Templates.Env[clip]);
			}
		}

		public void Step(float dt, float now)
		{
			switch (State)
			{
			case S.Spilling:
				m_timer -= dt;
				if (m_timer <= 0f)
				{
					State = S.Standing;
					HeatStep = 0;
					m_lastFire = now;
					Play(m_standAnim, "IgnisMoundHeat0");
				}
				break;
			case S.Standing:
				if (HeatStep > 0 && now - m_lastFire >= 10f)
				{
					HeatStep--;
					m_lastFire = now;
					Play(m_standAnim, HeatClips[HeatStep]);
				}
				break;
			case S.Slump:
				m_timer -= dt;
				if (m_timer <= 0f)
				{
					FormPool();
				}
				break;
			case S.Pool:
				if (!m_poolOn && now - PoolBorn >= 0.4f && (Object)(object)m_poolDamage != (Object)null)
				{
					m_poolOn = true;
					m_poolDamage.AnimDamageOn();
				}
				if (now - PoolBorn >= Tuning.PoolLife[Mathf.Clamp(m_hoard.Boss.BeatPhase, 1, 3) - 1])
				{
					StopDamage();
					State = S.PoolDull;
					m_timer = 1f;
					Play(m_floorAnim, "IgnisMoundPoolDull");
					m_hoard.Touch();
				}
				break;
			case S.PoolDull:
				m_timer -= dt;
				if (m_timer <= 0f)
				{
					State = S.Crust;
					m_timer = 2f;
					Play(m_floorAnim, "IgnisMoundCrust");
				}
				break;
			case S.Crust:
				m_timer -= dt;
				if (m_timer <= 0f)
				{
					State = S.CrustFade;
					m_timer = 4f;
					Play(m_floorAnim, "IgnisMoundCrustFade");
				}
				break;
			case S.CrustFade:
			case S.Draining:
				m_timer -= dt;
				if (m_timer <= 0f)
				{
					Gone();
				}
				break;
			case S.Smashing:
				m_timer -= dt;
				if (m_timer <= 0f)
				{
					Gone();
				}
				break;
			}
		}

		private void Gone()
		{
			State = S.Gone;
			SetSolid(on: false);
			if ((Object)(object)m_stand != (Object)null)
			{
				m_stand.SetActive(false);
			}
			if ((Object)(object)m_floor != (Object)null)
			{
				m_floor.SetActive(false);
			}
			if (IsSpill)
			{
				m_hoard.ReleaseSpill(m_spillIndex);
			}
			m_hoard.Touch();
		}
	}
	public class IgnisBrain : KitBrain
	{
	}
	public sealed class IgnisBoss : KitBoss
	{
		private delegate void CleanupStep();

		internal IgnisHoard Hoard;

		internal IgnisFirewash Wash;

		internal IgnisMind Mind;

		internal readonly List<IgnisMimic> Mimics = new List<IgnisMimic>();

		internal readonly List<KitStation> Fissures = new List<KitStation>();

		internal readonly List<KitStation> Chutes = new List<KitStation>();

		internal readonly List<IgnisDormantLook> DormantLooks = new List<IgnisDormantLook>();

		private float m_lastHitSound = -10f;

		private float m_nextFrameNote;

		private Health m_heroHealth;

		private readonly List<KeyValuePair<int, HitFilter>> m_filterIds = new List<KeyValuePair<int, HitFilter>>();

		private readonly List<int> m_markIds = new List<int>();

		protected override Vector2 BarLocal => Layout.BarLocal;

		internal int BeatPhase
		{
			get
			{
				if (Mind == null)
				{
					return 1;
				}
				return Mind.BeatPhase;
			}
		}

		private bool BotWindowOpen
		{
			get
			{
				if (Mind != null && !((KitBoss)this).Killed && ((KitBoss)this).Fighting && (Object)(object)((KitBoss)this).LifeBody != (Object)null)
				{
					return ((KitBoss)this).LifeBody.Alive;
				}
				return false;
			}
		}

		protected override void BuildArena(Room room)
		{
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			Hoard = new IgnisHoard(this, room);
			Exception ex = null;
			try
			{
				Hoard.Build();
			}
			catch (Exception ex2)
			{
				ex = ex2;
			}
			try
			{
				Wash = new IgnisFirewash(Hoard);
			}
			catch (Exception ex3)
			{
				Wash = null;
				((KitBoss)this).Ctx.Log.Warn("the Firewash rays were not built, Ignis fights without his breath: " + ex3);
			}
			if (ex != null)
			{
				throw new InvalidOperationException("the hoard build failed", ex);
			}
			for (int i = 0; i < Layout.Fissures.Length; i++)
			{
				bool flag = i < 3;
				KitStation val = ((KitBoss)this).SpawnStation(flag ? Templates.Fissure : Templates.FissureDormant, Layout.Fissures[i], IgnisStations.FissureSpec(flag ? 1 : 2));
				FlameRelay relay = ((Component)val).GetComponent<FlameRelay>();
				if ((Object)(object)relay != (Object)null)
				{
					relay.Hoard = Hoard;
					val.Fired += delegate
					{
						relay.Key = Hoard.NextKey();
					};
				}
				KitArt.SetDepthOffset(((Component)val).gameObject, 12f);
				if (!flag)
				{
					HoldDormant(val, "IgnisFissure_dormant");
				}
				Fissures.Add(val);
			}
			for (int num = 0; num < Layout.Chutes.Length; num++)
			{
				bool flag2 = num < 2;
				KitStation val2 = ((KitBoss)this).SpawnStation(flag2 ? Templates.Chute : Templates.ChuteSideDormant, Layout.Chutes[num], IgnisStations.ChuteSpec(!flag2, flag2 ? 1 : 2));
				IgnisStations.SetSpawnNode(val2);
				ChuteRelay component = ((Component)val2).GetComponent<ChuteRelay>();
				if ((Object)(object)component != (Object)null)
				{
					component.Hoard = Hoard;
				}
				if (!flag2)
				{
					HoldDormant(val2, "IgnisChuteSide_dormant");
				}
				Chutes.Add(val2);
			}
			IgnisNotes.Note("arena: " + Hoard.Mounds.Count + " mounds, " + Fissures.Count + " fissures, " + Chutes.Count + " chutes, " + DormantLooks.Count + " dormant looks, mimics " + (((Object)(object)Templates.MimicTemplate != (Object)null) ? "on" : ("off (" + Templates.MimicFailed + ")")));
		}

		private void HoldDormant(KitStation st, string clip)
		{
			try
			{
				IgnisDormantLook ignisDormantLook = IgnisDormantLook.Hold(st, Templates.Env[clip]);
				if ((Object)(object)ignisDormantLook != (Object)null)
				{
					DormantLooks.Add(ignisDormantLook);
				}
			}
			catch (Exception ex)
			{
				((KitBoss)this).Ctx.Log.WarnOnce("dormant look " + clip, ex);
			}
		}

		internal void WakeDormantLooks()
		{
			foreach (IgnisDormantLook dormantLook in DormantLooks)
			{
				if ((Object)(object)dormantLook != (Object)null)
				{
					dormantLook.Wake();
				}
			}
		}

		protected override KitBody SpawnBodies(Room room)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: 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_0100: Unknown result type (might be due to invalid IL or missing references)
			KitBody val = KitBodies.Spawn<IgnisBrain>((KitBoss)(object)this, Templates.BodyTemplate, Layout.BossStart, "Ignis");
			val.RefuseStatuses = true;
			HitFilter val2 = new HitFilter(ArmourFilter);
			KitHealth.SetFilter(val.Health, val2);
			TrackFilter(val.Health, val2);
			val.Damaged += OnBodyDamaged;
			Mind = new IgnisMind(this, val, Hoard, Wash);
			IgnisBodyEvents component = ((Component)val).GetComponent<IgnisBodyEvents>();
			if ((Object)(object)component != (Object)null)
			{
				component.Wash = Mind.OnWashEvent;
			}
			Hoard.PoolFormed += Mind.OnPoolFormed;
			val.Brain.Face(Vector2.left);
			if ((Object)(object)Templates.MimicTemplate != (Object)null)
			{
				for (int i = 0; i < Layout.Mimics.Length; i++)
				{
					try
					{
						Vector2 val3 = Layout.Mimics[i];
						KitBody val4 = KitBodies.Spawn<KitBrain>((KitBoss)(object)this, Templates.MimicTemplate, new Vector2(val3.x, val3.y - 8.5f), "IgnisMimic" + (i + 1));
						IgnisMimic component2 = ((Component)val4).GetComponent<IgnisMimic>();
						component2.Setup(val4, Hoard, "X" + (i + 1));
						TrackFilter(val4.Health, component2.FilterFn);
						if ((Object)(object)component2.Fodder != (Object)null)
						{
							m_markIds.Add(((Object)component2.Fodder).GetInstanceID());
						}
						Hoard.AddMimic(component2);
						Mimics.Add(component2);
					}
					catch (Exception ex)
					{
						((KitBoss)this).Ctx.Log.Warn("mimic X" + (i + 1) + " did not spawn, its spot is a cold mound: " + ex.Message);
						try
						{
							Hoard.AddInert(Layout.Mimics[i], "X" + (i + 1));
						}
						catch (Exception ex2)
						{
							((KitBoss)this).Ctx.Log.WarnOnce("inert mound", ex2);
						}
					}
				}
			}
			return val;
		}

		protected override IEnumerator Intro()
		{
			if ((Object)(object)((KitBoss)this).LifeBody != (Object)null)
			{
				((KitBoss)this).LifeBody.PlayCutscene(Templates.Body["IgnisDead"], false);
				IgnisCues.Play("IgnisSnore", ((Component)((KitBoss)this).LifeBody).transform);
			}
			yield return KitBoss.WaitGameTime(0.4f);
			if ((Object)(object)((KitBoss)this).LifeBody != (Object)null)
			{
				((KitBoss)this).LifeBody.PlayCutscene(Templates.Body["IgnisRoar"], false);
				Hoard.Rattle();
			}
			yield return KitBoss.WaitGameTime(2f);
		}

		protected override void OnFightStart()
		{
			if ((Object)(object)((KitBoss)this).LifeBody != (Object)null)
			{
				((KitBoss)this).LifeBody.EndAction();
			}
			SetHeroFilter(on: true);
			Mind.Start();
			Hoard.StartRegrowth();
			IgnisNotes.Note("fight: sounds " + (IgnisCues.Own ? "own" : "fallback") + ", mimics " + Mimics.Count);
		}

		protected override void OnPhase(int phase)
		{
			if (Mind != null)
			{
				Mind.QueueBeat(phase);
			}
		}

		protected override void KitUpdate()
		{
			float deltaTime = Time.deltaTime;
			if (Hoard != null)
			{
				Hoard.Step(deltaTime, ((KitBoss)this).Fighting);
			}
			if (Mind != null)
			{
				IgnisMound lyingPool = Mind.LyingPool;
				foreach (IgnisMimic mimic in Mimics)
				{
					if ((Object)(object)mimic != (Object)null)
					{
						mimic.Tick(deltaTime, ((KitBoss)this).UnpausedTime, lyingPool);
					}
				}
				if (((KitBoss)this).Fighting)
				{
					Mind.Step(deltaTime);
				}
			}
			if (KitSelfTest.Active && ((KitBoss)this).UnpausedTime >= m_nextFrameNote && ((KitBoss)this).Fighting)
			{
				m_nextFrameNote = ((KitBoss)this).UnpausedTime + 10f;
				IgnisNotes.Note("frame " + (deltaTime * 1000f).ToString("0.0") + " ms, tongues " + IgnisTongue.Live.Count + ", fissure puffs " + Reported(fissures: true) + ", boulders " + Reported(fissures: false));
			}
		}

		private int Reported(bool fissures)
		{
			int num = 0;
			foreach (KitStation item in fissures ? Fissures : Chutes)
			{
				if ((Object)(object)item == (Object)null)
				{
					continue;
				}
				if (fissures)
				{
					FlameRelay component = ((Component)item).GetComponent<FlameRelay>();
					if ((Object)(object)component != (Object)null)
					{
						num += component.Reported;
					}
				}
				else
				{
					ChuteRelay component2 = ((Component)item).GetComponent<ChuteRelay>();
					if ((Object)(object)component2 != (Object)null)
					{
						num += component2.Reported;
					}
				}
			}
			return num;
		}

		private HitVerdict ArmourFilter(Health health, DamageInfo info, bool hitFriendly)
		{
			if (KitHealth.IsHeroHit(info))
			{
				bool flag = Mind != null && Mind.Soft;
				SetFlash(health, flag);
				info.m_amount *= (flag ? 1.6f : 0.35f);
				return (HitVerdict)0;
			}
			return (HitVerdict)1;
		}

		private void SetFlash(Health health, bool on)
		{
			if ((Object)(object)health == (Object)null)
			{
				return;
			}
			try
			{
				Util.Set((object)health, "m_flashOnHit", (object)on);
			}
			catch (Exception ex)
			{
				if (((KitBoss)this).Ctx != null)
				{
					((KitBoss)this).Ctx.Log.WarnOnce("ignis hit flash", ex);
				}
			}
		}

		private void OnBodyDamaged(DamageInfo info)
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: 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_0074: 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_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_0092: 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_0098: 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_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: 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_0115: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if ((Object)(object)((KitBoss)this).LifeBody == (Object)null || info == null || info.m_amount <= 0f)
				{
					return;
				}
				bool flag = Mind != null && Mind.Soft;
				Player val = Util.Hero();
				Vector2 val2 = Vector2.op_Implicit(((Component)((KitBoss)this).LifeBody).transform.position) + Layout.HitZoneCentre;
				Vector2 val3 = val2;
				if ((Object)(object)val != (Object)null)
				{
					Vector2 val4 = Vector2.op_Implicit(((Component)val).transform.position) + new Vector2(0f, 9f) - val2;
					val3 = val2 + new Vector2(Mathf.Clamp(val4.x, (0f - Layout.HitZoneSize.x) * 0.4f, Layout.HitZoneSize.x * 0.4f), Mathf.Clamp(val4.y, (0f - Layout.HitZoneSize.y) * 0.4f, Layout.HitZoneSize.y * 0.4f));
				}
				if (flag)
				{
					if ((Object)(object)Templates.BloodSplash != (Object)null)
					{
						KitFx.SpawnFx(Templates.BloodSplash, val3, 0f);
					}
				}
				else
				{
					IgnisFx.OneShot(((Component)((KitBoss)this).Arena).transform, "IgnisCrustSpark", val3, 0f - (val3.y - ((Component)((KitBoss)this).LifeBody).transform.position.y) - 2f, (Anchor)4);
				}
				if (((KitBoss)this).UnpausedTime - m_lastHitSound >= 0.25f)
				{
					m_lastHitSound = ((KitBoss)this).UnpausedTime;
					IgnisCues.Play(flag ? "IgnisHurt" : "IgnisClink", ((Component)((KitBoss)this).LifeBody).transform);
				}
			}
			catch (Exception ex)
			{
				((KitBoss)this).Ctx.Log.WarnOnce("ignis hit feedback", ex);
			}
		}

		private void SetHeroFilter(bool on)
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Expected O, but got Unknown
			try
			{
				if ((Object)(object)m_heroHealth != (Object)null)
				{
					KitHealth.ClearFilter(m_heroHealth);
					m_heroHealth = null;
				}
				if (on)
				{
					Player val = Util.Hero();
					m_heroHealth = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<Health>() : null);
					if ((Object)(object)m_heroHealth != (Object)null)
					{
						HitFilter val2 = new HitFilter(HeroFilter);
						KitHealth.SetFilter(m_heroHealth, val2);
						TrackFilter(m_heroHealth, val2);
					}
				}
			}
			catch (Exception ex)
			{
				((KitBoss)this).Ctx.Log.WarnOnce("ignis hero filter", ex);
			}
		}

		private HitVerdict HeroFilter(Health health, DamageInfo info, bool hitFriendly)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				GameObject val = ((info != null && info.m_source != null) ? info.m_source.m_source : null);
				IgnisTongue ignisTongue = (((Object)(object)val != (Object)null) ? val.GetComponent<IgnisTongue>() : null);
				if ((Object)(object)ignisTongue != (Object)null && ignisTongue.Shadowed(((KitBoss)this).RoomLocal(((Component)health).transform.position)))
				{
					return (HitVerdict)1;
				}
			}
			catch (Exception ex)
			{
				((KitBoss)this).Ctx.Log.WarnOnce("ignis hero filter hit", ex);
			}
			return (HitVerdict)0;
		}

		protected override void OnBossDying(DamageInfo info)
		{
			Safe("die mind", delegate
			{
				if (Mind != null)
				{
					Mind.Die();
				}
			});
			Safe("die wash", delegate
			{
				if (Wash != null)
				{
					Wash.Hide();
				}
			});
			Safe("die tongues", IgnisTongue.KillAll);
			Safe("die hoard", delegate
			{
				if (Hoard != null)
				{
					Hoard.StopAll();
				}
			});
			Safe("die mimics", FreezeMimics);
			Safe("die hero filter", delegate
			{
				SetHeroFilter(on: false);
			});
			Safe("die armour filter", ClearArmourFilter);
			IgnisNotes.Note("Ignis killed");
		}

		protected override void OnHeroKilledKit(Player hero)
		{
			Safe("gloat hero filter", delegate
			{
				SetHeroFilter(on: false);
			});
			Safe("gloat armour filter", ClearArmourFilter);
			Safe("gloat mimics", FreezeMimics);
			Safe("gloat mind", delegate
			{
				if (Mind != null)
				{
					Mind.Gloat();
				}
			});
			Safe("gloat wash", delegate
			{
				if (Wash != null)
				{
					Wash.Hide();
				}
			});
			Safe("gloat tongues", IgnisTongue.KillAll);
			Safe("gloat hoard", delegate
			{
				if (Hoard != null)
				{
					Hoard.StopAll();
				}
			});
		}

		private void Safe(string what, CleanupStep step)
		{
			try
			{
				step();
			}
			catch (Exception ex)
			{
				((KitBoss)this).Ctx.Log.WarnOnce("ignis " + what, ex);
			}
		}

		private void TrackFilter(Health h, HitFilter filter)
		{
			if ((Object)(object)h != (Object)null && filter != null)
			{
				m_filterIds.Add(new KeyValuePair<int, HitFilter>(((Object)h).GetInstanceID(), filter));
			}
		}

		private void FreezeMimics()
		{
			foreach (IgnisMimic mimic in Mimics)
			{
				if ((Object)(object)mimic != (Object)null)
				{
					mimic.Freeze();
				}
			}
		}

		private void ClearArmourFilter()
		{
			try
			{
				KitHealth.ClearFilter(((KitBoss)this).LifeHealth);
			}
			catch (Exception ex)
			{
				((KitBoss)this).Ctx.Log.WarnOnce("ignis armour filter", ex);
			}
		}

		protected override void OnFrozen(bool frozen)
		{
			if (Mind != null)
			{
				Mind.SetFrozen(frozen);
			}
		}

		protected override void OnCleanup()
		{
			Safe("cleanup hero filter", delegate
			{
				SetHeroFilter(on: false);
			});
			Safe("cleanup tongues", IgnisTongue.KillAll);
			Safe("cleanup hoard", delegate
			{
				if (Hoard != null)
				{
					Hoard.StopAll();
				}
			});
			Safe("cleanup armour filter", ClearArmourFilter);
			Safe("cleanup mimic filters", delegate
			{
				foreach (IgnisMimic mimic in Mimics)
				{
					if ((Object)(object)mimic != (Object)null)
					{
						mimic.ClearFilter();
					}
				}
			});
			Safe("cleanup kit ids", delegate
			{
				IgnisKitIds.Forget(m_filterIds, m_markIds);
			});
			m_filterIds.Clear();
			m_markIds.Clear();
			Safe("cleanup stations", IgnisStations.Forget);
		}

		public override bool GetVulnerable()
		{
			Vector2 p;
			return BotWindow(out p);
		}

		public override Vector2 GetVulnerableTargetPosition()
		{
			//IL_0022: 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)
			//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)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			if (BotWindow(out var p))
			{
				return Vector2.op_Implicit(((KitBoss)this).World(p)) - Tuning.BotOffset;
			}
			return ((KitBoss)this).GetVulnerableTargetPosition();
		}

		private bool BotWindow(out Vector2 p)
		{
			//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_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			p = Vector2.zero;
			if (!BotWindowOpen)
			{
				return false;
			}
			Player val = Util.Hero();
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			PlayerMovement component = ((Component)val).GetComponent<PlayerMovement>();
			float num = (((Object)(object)component != (Object)null) ? component.GetSpeedMax() : 0f);
			return Mind.BotWindow(((KitBoss)this).RoomLocal(((Component)val).transform.position), (num > 1f) ? num : 73f, out p);
		}

		internal bool BotCoverSpot(Vector2 heroFeet, float heroSpeed, out Vector2 world)
		{
			//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_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			world = Vector2.zero;
			if (!BotWindowOpen || !Mind.BotCover(((KitBoss)this).RoomLocal(Vector2.op_Implicit(heroFeet)), heroSpeed, out var target))
			{
				return false;
			}
			world = Vector2.op_Implicit(((KitBoss)this).World(target));
			return true;
		}

		public override bool ShouldForceBotExitFodder(GameObject obj)
		{
			if ((Object)(object)obj != (Object)null)
			{
				return (Object)(object)obj.GetComponent<IgnisMimic>() != (Object)null;
			}
			return false;
		}

		internal Rect BodyRect()
		{
			//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_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: 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_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: 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_0055: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val = ((KitBoss)this).RoomLocal(((Component)((KitBoss)this).LifeBody).transform.position);
			Vector2 bodyBox = Layout.BodyBox;
			return new Rect(val.x - bodyBox.x * 0.5f, val.y + 7f - bodyBox.y * 0.5f, bodyBox.x, bodyBox.y);
		}

		internal float CapsuleEntry(Vector2 a, Vector2 b)
		{
			//IL_0021: 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_0024: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)((KitBoss)this).LifeBody == (Object)null || !((KitBoss)this).LifeBody.Alive)
			{
				return -1f;
			}
			return IgnisHoard.SegmentBox(a, b, BodyRect());
		}

		internal float CapsuleDistance(Vector2 a, Vector2 b)
		{
			//IL_0021: 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_0024: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)((KitBoss)this).LifeBody == (Object)null || !((KitBoss)this).LifeBody.Alive)
			{
				return float.MaxValue;
			}
			return Geo.SegRect(a, b, BodyRect());
		}
	}
	internal static class IgnisKitIds
	{
		private static bool s_resolved;

		private static IDictionary<int, HitFilter> s_filters;

		private static ICollection<int> s_humanOnly;

		private static void Resolve()
		{
			if (s_resolved)
			{
				return;
			}
			s_resolved = true;
			try
			{
				FieldInfo field = typeof(KitHealth).GetField("s_filters", BindingFlags.Static | BindingFlags.NonPublic);
				s_filters = (((object)field != null) ? (field.GetValue(null) as IDictionary<int, HitFilter>) : null);
				FieldInfo field2 = typeof(KitStations).GetField("s_humanOnly", BindingFlags.Static | BindingFlags.NonPublic);
				s_humanOnly = (((object)field2 != null) ? (field2.GetValue(null) as ICollection<int>) : null);
			}
			catch (Exception ex)
			{
				if (Plugin.Ctx != null)
				{
					Plugin.Ctx.Log.WarnOnce("ignis kit registries", ex);
				}
			}
			if ((s_filters == null || s_humanOnly == null) && Plugin.Ctx != null)
			{
				Plugin.Ctx.Log.WarnOnce("ignis kit registries", "the kit's filter or human-only registry is not readable by id; after a quit mid-fight its entries stay until the game closes");
			}
		}

		public static void Forget(List<KeyValuePair<int, HitFilter>> filters, List<int> marks)
		{
			Resolve();
			if (s_filters != null && filters != null)
			{
				foreach (KeyValuePair<int, HitFilter> filter in filters)
				{
					if (s_filters.TryGetValue(filter.Key, out var value) && value != null && ((object)value).Equals((object?)filter.Value))
					{
						s_filters.Remove(filter.Key);
					}
				}
			}
			if (s_humanOnly == null || marks == null)
			{
				return;
			}
			foreach (int mark in marks)
			{
				s_humanOnly.Remove(mark);
			}
		}
	}
	internal static class Layout
	{
		public static readonly Vector2[] Polygon = (Vector2[])(object)new Vector2[16]
		{
			new Vector2(122.41f, -48.53f),
			new Vector2(95f, -63.82f),
			new Vector2(70f, -67f),
			new Vector2(-58f, -67f),
			new Vector2(-111.9f, -56.38f),
			new Vector2(-133.4f, -32.59f),
			new Vector2(-138.39f, -3.18f),
			new Vector2(-136.8f, 28.21f),
			new Vector2(-114.8f, 44.4f),
			new Vector2(-60.54f, 54.31f),
			new Vector2(5.02f, 56.3f),
			new Vector2(47.58f, 55.3f),
			new Vector2(98.34f, 49.36f),
			new Vector2(133.37f, 35.9f),
			new Vector2(139.24f, 5.83f),
			new Vector2(132.97f, -31.93f)
		};

		public static readonly Vector2 BossStart = new Vector2(8f, 24f);

		public static readonly Vector2 BarLocal = new Vector2(0f, 82.59f);

		public static readonly Rect Heap = new Rect(-56f, 40f, 112f, 16f);

		public static readonly Vector2 HeapSprite = new Vector2(0f, 40f);

		public static readonly Vector2[] Mounds = (Vector2[])(object)new Vector2[7]
		{
			new Vector2(-100f, 2f),
			new Vector2(-64f, -34f),
			new Vector2(-34f, 16f),
			new Vector2(6f, -44f),
			new Vector2(40f, 6f),
			new Vector2(70f, -36f),
			new Vector2(106f, 4f)
		};

		public const float MoundW = 26f;

		public const float MoundH = 16f;

		public const float PoolW = 34f;

		public const float PoolH = 14f;

		public const float MoundArtLift = 8.5f;

		public static readonly Vector2[] Mimics = (Vector2[])(object)new Vector2[2]
		{
			new Vector2(-14f, -14f),
			new Vector2(110f, -35f)
		};

		public static readonly Vector2[] Fissures = (Vector2[])(object)new Vector2[5]
		{
			new Vector2(-77f, 18f),
			new Vector2(1f, 6f),
			new Vector2(70f, 12f),
			new Vector2(37f, -30f),
			new Vector2(-29f, -42f)
		};

		public const int FissuresLive = 3;

		public static readonly Vector2[] Chutes = (Vector2[])(object)new Vector2[3]
		{
			new Vector2(-80f, 60f),
			new Vector2(73f, 60f),
			new Vector2(-136f, -24f)
		};

		public const int ChutesLive = 2;

		public static readonly Vector2 FissureSeat = new Vector2(0f, 0f);

		public static readonly Vector2 ChuteSeat = new Vector2(0f, 0f);

		public static readonly Vector2 ChuteSideSeat = new Vector2(8f, 10f);

		public const float ChuteMouthOffsetY = -20f;

		public const float ChuteSideMouthOffsetY = 6f;

		public const float ChuteFxOffsetY = 0f;

		public const float ChuteAim = 270f;

		public const float ChuteSideAim = 0f;

		public static readonly Vector2 ChuteRange = new Vector2(200f, 340f);

		public static readonly Vector2 ChuteSideRange = new Vector2(-70f, 70f);

		public static readonly Vector2[] Spills = (Vector2[])(object)new Vector2[6]
		{
			new Vector2(-98f, 34f),
			new Vector2(-42f, 32f),
			new Vector2(44f, 32f),
			new Vector2(91f, 34f),
			new Vector2(-116f, -21f),
			new Vector2(117f, -5f)
		};

		public const float SpillGap = 14f;

		public static readonly Vector2 BackWall = new Vector2(-140f, 46f);

		public const float BackWallZ = 70f;

		public const float FloorCaveZ = 99f;

		public const float FloorZ = 50f;

		public const float CapsuleRadius = 6f;

		public const float CapsuleHalfSeg = 8f;

		public const float CapsuleCentreY = 7f;

		public static readonly Vector2 BodyBox = new Vector2(56f, 16f);

		public static readonly Vector2 Mouth = new Vector2(44f, 30f);

		public static readonly Vector2 FloorMouth = new Vector2(38f, 4f);

		public static readonly Vector2 AttackNode = new Vector2(0f, 18f);

		public static readonly Vector2 BiteFx = new Vector2(35f, 4f);

		public static readonly Vector2 BiteBox = new Vector2(42f, 20f);

		public static readonly Vector2 TailFx = new Vector2(-38f, 6f);

		public static readonly Vector2 TailBox = new Vector2(60f, 30f);

		public static readonly Vector2 WallowBelly = new Vector2(0f, 6f);

		public static readonly Vector2 HitZoneSize = new Vector2(72f, 40f);

		public static readonly Vector2 HitZoneCentre = new Vector2(0f, 24f);

		public const float MimicCapsuleRadius = 6f;

		public const float MimicCapsuleHeight = 22f;

		public static readonly Vector2 MimicSnapFx = new Vector2(18f, 8.5f);

		public static readonly Vector2 MimicTrigger = new Vector2(34f, 26f);

		public static readonly Vector2 MimicHitZone = new Vector2(26f, 20f);

		public const float MimicHitZoneY = 10f;

		public const float MimicClampInset = 2f;
	}
	internal sealed class IgnisMimic : MonoBehaviour
	{
		public KitBody Body;

		public IgnisHoard Hoard;

		public string Name;

		private PropFodder m_fodder;

		private bool m_worn;

		private float m_lockUntil = -1f;

		private bool m_locked;

		private IgnisMound m_sitPool;

		private float m_sitSince;

		private bool m_gulping;

		private float m_gulpEnd;

		private Vector2 m_lastPos;

		private bool m_frozen;

		public bool Alive
		{
			get
			{
				if ((Object)(object)Body != (Object)null)
				{
					return Body.Alive;
				}
				return false;
			}
		}

		public bool IsCover => Alive;

		public bool Inhabited
		{
			get
			{
				if ((Object)(object)m_fodder != (Object)null)
				{
					return m_fodder.GetInhabited();
				}
				return false;
			}
		}

		public bool Worn
		{
			get
			{
				if (m_worn && !m_locked && (Object)(object)m_fodder != (Object)null)
				{
					return m_fodder.GetInhabited();
				}
				return false;
			}
		}

		public bool Gulping => m_gulping;

		public IgnisMound GulpPool
		{
			get
			{
				if (!m_gulping)
				{
					return null;
				}
				return m_sitPool;
			}
		}

		public Rect CoverBoxLocal
		{
			get
			{
				//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_0016: Unknown result type (might be due to invalid IL or missing references)
				//IL_0017: Unknown result type (might be due to invalid IL or missing references)
				//IL_001d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0029: Unknown result type (might be due to invalid IL or missing references)
				//IL_002e: Unknown result type (might be due to invalid IL or missing references)
				Vector2 val = Hoard.Local(((Component)this).transform.position);
				return IgnisHoard.MoundBox(new Vector2(val.x, val.y + 8.5f));
			}
		}

		internal HitFilter FilterFn { get; private set; }

		internal PropFodder Fodder => m_fodder;

		public void Setup(KitBody body, IgnisHoard hoard, string name)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: 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_004a: Expected O, but got Unknown
			Body = body;
			Hoard = hoard;
			Name = name;
			m_fodder = ((Component)this).GetComponent<PropFodder>();
			m_lastPos = hoard.Local(((Component)this).transform.position);
			FilterFn = new HitFilter(Filter);
			KitHealth.SetFilter(body.Health, FilterFn);
			body.RefuseStatuses = true;
			body.VelocityOverride = Clamp;
			if ((Object)(object)m_fodder != (Object)null)
			{
				KitStations.MarkHumanOnly((Prop)(object)m_fodder);
			}
		}

		private void OnInhabitAI(PlayerData data)
		{
			try
			{
				m_worn = true;
				SetLoop("IgnisMimicWorn", "IgnisMimicShuffle");
				if ((Object)(object)Body != (Object)null)
				{
					Body.PlayStatus(Templates.Env["IgnisMimicAwake"]);
				}
				IgnisNotes.Note(Name + " worn by " + ((data != null && data.IsBot) ? "a bot (refused path)" : "a human ghost"));
			}
			catch (Exception ex)
			{
				Plugin.Ctx.Log.WarnOnce("mimic inhabit", ex);
			}
		}

		private void OnUninhabitAI()
		{
			try
			{
				m_worn = false;
				CancelGulp();
				if (!m_locked)
				{
					SetLoop("IgnisMimicIdle", "IgnisMimicIdle");
				}
				if ((Object)(object)Body != (Object)null && (Object)(object)Body.Brain != (Object)null)
				{
					Body.Brain.Stop();
				}
			}
			catch (Exception ex)
			{
				Plugin.Ctx.Log.WarnOnce("mimic uninhabit", ex);
			}
		}

		private void SetLoop(string idle, string run)
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Invalid comparison between Unknown and I4
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Invalid comparison between Unknown and I4
			if (!((Object)(object)Body == (Object)null) && !((Object)(object)Body.Player == (Object)null))
			{
				ClipLibrary env = Templates.Env;
				Util.Set((object)Body.Player, "m_animationIdle", (object)env[idle]);
				Util.Set((object)Body.Player, "m_animationRun", (object)env[run]);
				ePlayerState state = Body.Player.GetState();
				if ((int)state == 2 && (Object)(object)Body.Anim != (Object)null)
				{
					Body.Anim.Play(env[idle]);
				}
				else if ((int)state == 3 && (Object)(object)Body.Anim != (Object)null)
				{
					Body.Anim.Play(env[run]);
				}
			}
		}

		private HitVerdict Filter(Health health, DamageInfo info, bool hitFriendly)
		{
			try
			{
				if (KitHealth.IsHeroHit(info) && Worn)
				{
					Eject();
				}
			}
			catch (Exception ex)
			{
				Plugin.Ctx.Log.WarnOnce("mimic filter", ex);
			}
			return (HitVerdict)1;
		}

		private void Eject()
		{
			CancelGulp();
			m_locked = true;
			m_lockUntil = Hoard.Now + 6f;
			if ((Object)(object)m_fodder != (Object)null)
			{
				m_fodder.DisableAction();
			}
			m_worn = false;
			SetLoop("IgnisMimicDazed", "IgnisMimicDazed");
			if ((Object)(object)Body != (Object)null)
			{
				Body.Stun(6f, Templates.Env["IgnisMimicDazed"]);
			}
			IgnisCues.Play("IgnisMimicEject", ((Component)this).transform);
			IgnisNotes.Note(Name + " ejected by a hero hit");
		}

		private void CancelGulp()
		{
			if (m_gulping && (Object)(object)Body != (Object)null)
			{
				Body.EndAction();
				if ((Object)(object)Body.Movement != (Object)null)
				{
					Body.Movement.InputOn("IgnisGulp");
				}
			}
			m_gulping = false;
			m_sitPool = null;
		}

		private Vector3? Clamp()
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: 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_0074: 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: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: 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_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: 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)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: 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_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: 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_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Body == (Object)null || (Object)(object)Body.Body == (Object)null)
			{
				return null;
			}
			Vector3 velocity = Body.Body.velocity;
			if (((Vector3)(ref velocity)).sqrMagnitude < 0.01f)
			{
				return null;
			}
			Vector2 val = Hoard.Local(((Component)this).transform.position);
			float fixedDeltaTime = Time.fixedDeltaTime;
			if (FootprintInside(val + Vector2.op_Implicit(velocity) * fixedDeltaTime))
			{
				return null;
			}
			Vector3 val2 = default(Vector3);
			((Vector3)(ref val2))..ctor(velocity.x, 0f, velocity.z);
			if (FootprintInside(val + Vector2.op_Implicit(val2) * fixedDeltaTime))
			{
				return val2;
			}
			Vector3 val3 = default(Vector3);
			((Vector3)(ref val3))..ctor(0f, velocity.y, velocity.z);
			if (FootprintInside(val + Vector2.op_Implicit(val3) * fixedDeltaTime))
			{
				return val3;
			}
			return new Vector3(0f, 0f, velocity.z);
		}

		internal static bool FootprintInside(Vector2 pivot)
		{
			//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_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			Rect val = IgnisHoard.MoundBox(new Vector2(pivot.x, pivot.y + 8.5f));
			float inset = 2f;
			if (Geo.InsideInset(new Vector2(((Rect)(ref val)).xMin, ((Rect)(ref val)).yMin), inset) && Geo.InsideInset(new Vector2(((Rect)(ref val)).xMax, ((Rect)(ref val)).yMin), inset) && Geo.InsideInset(new Vector2(((Rect)(ref val)).xMin, ((Rect)(ref val)).yMax), inset))
			{
				return Geo.InsideInset(new Vector2(((Rect)(ref val)).xMax, ((Rect)(ref val)).yMax), inset);
			}
			return false;
		}

		public void Tick(float dt, float now, IgnisMound ignisPool)
		{
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: 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_0098: 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_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: 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_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			if (!Alive || m_frozen)
			{
				return;
			}
			if (m_locked && now >= m_lockUntil)
			{
				m_locked = false;
				if ((Object)(object)m_fodder != (Object)null)
				{
					m_fodder.EnableAction();
				}
				SetLoop("IgnisMimicIdle", "IgnisMimicIdle");
				if ((Object)(object)Body != (Object)null)
				{
					Body.EndAction();
				}
			}
			Vector2 val = Hoard.Local(((Component)this).transform.position);
			float num;
			if (!(dt > 0f))
			{
				num = 0f;
			}
			else
			{
				Vector2 val2 = val - m_lastPos;
				num = ((Vector2)(ref val2)).magnitude / dt;
			}
			float num2 = num;
			m_lastPos = val;
			if (m_gulping)
			{
				if (m_sitPool == null || !m_sitPool.IsLivePool || m_sitPool == ignisPool)
				{
					CancelGulp();
				}
				else if (now >= m_gulpEnd)
				{
					IgnisMound sitPool = m_sitPool;
					m_gulping = false;
					m_sitPool = null;
					sitPool.Take();
					IgnisNotes.Note(Name + " gulped " + sitPool.Name);
				}
				return;
			}
			if (!Worn)
			{
				m_sitPool = null;
				return;
			}
			Vector2 val3 = default(Vector2);
			((Vector2)(ref val3))..ctor(val.x, val.y + 8.5f);
			IgnisMound ignisMound = null;
			foreach (IgnisMound mound in Hoard.Mounds)
			{
				if (mound.IsLivePool && mound != ignisPool)
				{
					Rect poolBox = mound.PoolBox;
					float num3 = 4f;
					if (val3.x >= ((Rect)(ref poolBox)).xMin - num3 && val3.x <= ((Rect)(ref poolBox)).xMax + num3 && val3.y >= ((Rect)(ref poolBox)).yMin - num3 && val3.y <= ((Rect)(ref poolBox)).yMax + num3)
					{
						ignisMound = mound;
						break;
					}
				}
			}
			if (ignisMound == null || num2 > 2f)
			{
				m_sitPool = null;
			}
			else if (m_sitPool != ignisMound)
			{
				m_sitPool = ignisMound;
				m_sitSince = now;
			}
			else
			{
				if (!(now - m_sitSince >= 0.4f))
				{
					return;
				}
				m_gulping = true;
				m_gulpEnd = now + 1f;
				if ((Object)(object)Body != (Object)null)
				{
					Body.PlayStatus(Templates.Env["IgnisMimicGulp"]);
					if ((Object)(object)Body.Movement != (Object)null)
					{
						Body.Movement.InputOff("IgnisGulp", 1f);
					}
				}
			}
		}

		public void Freeze()
		{
			m_frozen = true;
			CancelGulp();
			if ((Object)(object)m_fodder != (Object)null)
			{
				m_fodder.DisableAction();
			}
			if ((Object)(object)Body != (Object)null && (Object)(object)Body.Brain != (Object)null)
			{
				Body.Brain.Stop();
			}
		}

		internal void ClearFilter()
		{
			if ((Object)(object)Body != (Object)null && (Object)(object)Body.Health != (Object)null)
			{
				KitHealth.ClearFilter(Body.Health);
			}
		}

		private void OnDestroy()
		{
			if ((Object)(object)m_fodder != (Object)null)
			{
				KitStations.Unmark((Prop)(object)m_fodder);
			}
			ClearFilter();
		}
	}
	internal sealed class IgnisMind
	{
		private enum St
		{
			Asleep,
			Hunt,
			Attack,
			Inhale,
			Greed,
			GreedWalk,
			Robbed,
			Wallow,
			Regild,
			Beat,
			Dead,
			Gloat
		}

		private static readonly Color SatedTint = new Color(1f, 0.85f, 0.35f, 0.45f);

		private static readonly Color SeamsTint = new Color(1f, 0.3f, 0.1f, 0.35f);

		private readonly IgnisBoss m_boss;

		private readonly KitBody m_body;

		private readonly IgnisHoard m_hoard;

		private readonly IgnisFirewash m_wash;

		private readonly IgnisPath m_path = new IgnisPath();

		private readonly Queue<int> m_beats = new Queue<int>();

		private St m_st;

		private float m_t0;

		private bool m_started;

		private bool m_frozen;

		private float m_nextWash;

		private float m_nextBite;

		private float m_nextTail;

		private float m_satedUntil = -1f;

		private float m_tailSince = -1f;

		private float m_behindSince = -1f;

		private float m_readySoundAt;

		private bool m_smoke;

		private bool m_resumeGreed;

		private IgnisMound m_target;

		private IgnisMound m_lying;

		private Vector2 m_spot;

		private IgnisMound m_spotFor;

		private bool m_spotOk;

		private int m_waves;

		private int m_wave;

		private float[] m_releaseAt = new float[3];

		private bool m_statusPlayed;

		private bool m_released;

		private bool m_holdDone;

		private float m_statusAt;

		private float m_deadline;

		private float m_aim;

		private float m_releasedAim;

		private Vector2 m_fireOrigin;

		private float m_fireAim;

		private float m_fireUntil = -1f;

		private int m_facing = 1;

		private int m_tongues;

		public int BeatPhase { get; private set; }

		private float Now => ((KitBoss)m_boss).UnpausedTime;

		private int P => Mathf.Clamp(BeatPhase, 1, 3) - 1;

		public bool Wallowing
		{
			get
			{
				if (m_st != St.Wallow)
				{
					return m_st == St.Regild;
				}
				return true;
			}
		}

		public bool Soft => m_st == St.Wallow;

		public IgnisMound LyingPool
		{
			get
			{
				if (!Wallowing)
				{
					return null;
				}
				return m_lying;
			}
		}

		public bool Sated => m_satedUntil > 0f;

		public bool Dead => m_st == St.Dead;

		private Vector2 Pivot => m_hoard.Local(((Component)m_body).transform.position);

		private int Facing
		{
			get
			{
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				if (!(((Component)m_body).transform.localScale.x >= 0f))
				{
					return -1;
				}
				return 1;
			}
		}

		private bool Free
		{
			get
			{
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0010: Unknown result type (might be due to invalid IL or missing references)
				//IL_0011: Unknown result type (might be due to invalid IL or missing references)
				//IL_0013: Invalid comparison between Unknown and I4
				//IL_0015: Unknown result type (might be due to invalid IL or missing references)
				//IL_0017: Invalid comparison between Unknown and I4
				ePlayerState state = m_body.Player.GetState();
				if ((int)state != 2)
				{
					return (int)state == 3;
				}
				return true;
			}
		}

		private bool FireLive
		{
			get
			{
				if (Now < m_fireUntil)
				{
					return IgnisTongue.Live.Count > 0;
				}
				return false;
			}
		}

		public IgnisMind(IgnisBoss boss, KitBody body, IgnisHoard hoard, IgnisFirewash wash)
		{
			m_boss = boss;
			m_body = body;
			m_hoard = hoard;
			m_wash = wash;
			BeatPhase = 1;
		}

		private static Vector2 FloorMouth(Vector2 pivot, int f)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			return new Vector2(pivot.x + Layout.FloorMouth.x * (float)f, pivot.y + Layout.FloorMouth.y);
		}

		private static bool HeroOverlaps(Vector2 heroFeet, Vector2 centre, Vector2 size)
		{
			//IL_0000: 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_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_007d: 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)
			float num = heroFeet.x - 4f;
			float num2 = heroFeet.x + 4f;
			float y = heroFeet.y;
			float num3 = heroFeet.y + 18f;
			float num4 = centre.x - size.x * 0.5f + 2f;
			float num5 = centre.x + size.x * 0.5f - 2f;
			float num6 = centre.y - size.y * 0.5f + 2f;
			float num7 = centre.y + size.y * 0.5f - 2f;
			if (num < num5 && num4 < num2 && y < num7)
			{
				return num6 < num3;
			}
			return false;
		}

		private bool BiteCovers(Vector2 pivot, Vector2 hero, int f, out float tilt)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: 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_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			tilt = 0f;
			float num = (hero.x - pivot.x) * (float)f;
			float num2 = hero.y + 9f - (pivot.y + Layout.BiteFx.y);
			if (num <= 4f)
			{
				return false;
			}
			float num3 = 0.43633232f;
			tilt = Mathf.Clamp(Mathf.Atan2(num2, num), 0f - num3, num3);
			Vector2 centre = default(Vector2);
			((Vector2)(ref centre))..ctor(pivot.x + (float)f * Layout.BiteFx.x * Mathf.Cos(tilt), pivot.y + Layout.BiteFx.y + Layout.BiteFx.x * Mathf.Sin(tilt));
			return HeroOverlaps(hero, centre, Layout.BiteBox);
		}

		private bool TailCovers(Vector2 pivot, Vector2 hero, int f)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			Vector2 centre = default(Vector2);
			((Vector2)(ref centre))..ctor(pivot.x + (float)f * Layout.TailFx.x, pivot.y + Layout.TailFx.y);
			return HeroOverlaps(hero, centre, Layout.TailBox);
		}

		private Vector2 BreathOrigin(Vector2 pivot, int f)
		{
			//IL_0000: 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_0007: 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_002e: 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_0055: 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)
			//IL_0066: 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)
			Vector2 val = FloorMouth(pivot, f);
			float num = Layout.FloorMouth.x - 14f;
			Vector2 val2 = default(Vector2);
			for (float num2 = 0f; num2 < num; num2 += 0.5f)
			{
				((Vector2)(ref val2))..ctor(val.x - (float)f * num2, val.y);
				if (!m_hoard.InsideCover(val2))
				{
					return val2;
				}
			}
			return new Vector2(val.x - (float)f * num, val.y);
		}

		private bool InWashCone(Vector2 pivot, Vector2 hero, int f)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: 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)
			Vector2 val = BreathOrigin(pivot, f);
			Vector2 val2 = hero + new Vector2(0f, 9f) - val;
			if (((Vector2)(ref val2)).magnitude > 160f)
			{
				return false;
			}
			float num = Mathf.Atan2(val2.y, val2.x) * 57.29578f;
			return Mathf.Abs(Mathf.DeltaAngle((f > 0) ? 0f : 180f, num)) <= 60f;
		}

		private static float ClampCone(float deg, int f)
		{
			float num = ((f > 0) ? 0f : 180f);
			float num2 = Mathf.Clamp(Mathf.DeltaAngle(num, deg), -60f, 60f);
			return num + num2;
		}

		public void Start()
		{
			m_started = true;
			m_nextWash = Now + 3f;
			m_nextBite = Now + 0.5f;
			m_nextTail = Now + 0.5f;
			Enter(St.Hunt);
		}

		public void QueueBeat(int phase)
		{
			m_beats.Enqueue(phase);
		}

		public void SetFrozen(bool frozen)
		{
			m_frozen = frozen;
			if (frozen)
			{
				if (m_st == St.Inhale)
				{
					AbortWash();
				}
				if ((Object)(object)m_body.Brain != (Object)null)
				{
					m_body.Brain.Stop();
				}
			}
		}

		public void Die()
		{
			m_st = St.Dead;
			if (m_wash != null)
			{
				m_wash.Hide();
			}
			m_beats.Clear();
			m_target = null;
			m_lying = null;
		}

		public void Gloat()
		{
			if (m_st != St.Dead)
			{
				if (m_wash != null)
				{
					m_wash.Hide();
				}
				m_beats.Cle

plugins/CrawlCustomBosses/CthulhuBoss.dll

Decompiled 4 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BossKit;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("CthulhuBoss")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("CthulhuBoss")]
[assembly: AssemblyTitle("CthulhuBoss")]
[assembly: AssemblyVersion("1.0.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 CthulhuBoss
{
	internal static class Decals
	{
		public static exSprite Make(DrownedGod god, ClipLibrary lib, string key, Vector2 roomLocal, Anchor anchor, float z, Transform parent = null)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			exSprite obj = KitArt.CreateSprite(parent ?? ((Component)((KitBoss)god).Arena).transform, lib.Sheet, key, 0, ((KitBoss)god).World(roomLocal), anchor, false, 0f);
			Transform transform = ((Component)obj).transform;
			transform.position = new Vector3(transform.position.x, transform.position.y, z);
			return obj;
		}

		public static exSpriteAnimation Play(exSprite spr, exSpriteAnimClip clip)
		{
			if ((Object)(object)spr == (Object)null || (Object)(object)clip == (Object)null)
			{
				return null;
			}
			exSpriteAnimation val = ((Component)spr).GetComponent<exSpriteAnimation>();
			if ((Object)(object)val == (Object)null)
			{
				val = ((Component)spr).gameObject.AddComponent<exSpriteAnimation>();
				val.playAutomatically = false;
			}
			val.Play(clip);
			return val;
		}

		public static bool Playing(exSprite spr)
		{
			exSpriteAnimation val = (((Object)(object)spr != (Object)null) ? ((Component)spr).GetComponent<exSpriteAnimation>() : null);
			if ((Object)(object)val != (Object)null)
			{
				return val.IsPlaying((string)null);
			}
			return false;
		}

		public static void Frame(exSprite spr, Sheet sheet, string key, int frame)
		{
			if (!((Object)(object)spr == (Object)null))
			{
				exSpriteAnimation component = ((Component)spr).GetComponent<exSpriteAnimation>();
				if ((Object)(object)component != (Object)null && component.IsPlaying((string)null))
				{
					component.Stop();
				}
				int[] array = sheet.Frames(key);
				spr.SetSprite(sheet.Atlas, array[Mathf.Clamp(frame, 0, array.Length - 1)], false);
			}
		}

		public static void Kill(ref exSprite spr)
		{
			if ((Object)(object)spr != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)spr).gameObject);
			}
			spr = null;
		}

		public static void Kill(exSprite spr)
		{
			if ((Object)(object)spr != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)spr).gameObject);
			}
		}

		public static void SortAboveFaces(DrownedGod god, exSprite spr)
		{
			//IL_0026: 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_0039: 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_0053: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)spr == (Object)null || (Object)(object)((Component)spr).GetComponent<DepthHandler>() != (Object)null)
			{
				return;
			}
			Transform transform = ((Component)spr).transform;
			float num = 26f - ((KitBoss)god).RoomLocal(transform.position).y;
			transform.position = new Vector3(transform.position.x, transform.position.y, 0f);
			DepthHandler val = ((Component)spr).gameObject.AddComponent<DepthHandler>();
			KitArt.SetDepthOffset(((Component)spr).gameObject, num);
			try
			{
				Util.Call((object)val, "AnimDepth", new object[1] { num });
			}
			catch (Exception ex)
			{
				Plugin.Ctx.Log.WarnOnce("telegraph depth", ex);
			}
		}

		public static void SetLocal(DrownedGod god, exSprite spr, Vector2 roomLocal)
		{
			//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)
			//IL_0011: 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_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)spr == (Object)null))
			{
				Vector3 val = ((KitBoss)god).World(roomLocal);
				((Component)spr).transform.position = new Vector3(Mathf.Round(val.x), Mathf.Round(val.y), ((Component)spr).transform.position.z);
			}
		}
	}
	internal sealed class Dream
	{
		private sealed class Face
		{
			public float SlotX;

			public bool Real;

			public exSprite Spr;

			public exSprite Pupils;

			public Hittable Hit;

			public bool Gone;

			public bool Looping;

			public float LoopAt;

			public float KillAt = -1f;

			public float PendingAt = -1f;
		}

		private readonly DrownedGod m_god;

		private readonly List<Face> m_faces = new List<Face>();

		private float m_nextPupil;

		private float m_realHitAt = float.NegativeInfinity;

		public int RealSlot { get; private set; }

		public int BotSlot { get; private set; }

		private ClipLibrary Lib => DrownedTemplates.Body;

		public bool Active { get; private set; }

		public bool Revealed { get; private set; }

		public Dream(DrownedGod god)
		{
			m_god = god;
		}

		public float SlotX(int i)
		{
			return (float)(i - 1) * 44f;
		}

		public void Begin(float now)
		{
			//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_0081: 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_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			Clear();
			Active = true;
			RealSlot = Random.Range(0, 3);
			for (int i = 0; i < 3; i++)
			{
				Face face = new Face
				{
					SlotX = SlotX(i),
					Real = (i == RealSlot)
				};
				Vector3 val = ((KitBoss)m_god).World(new Vector2(face.SlotX, 20f));
				face.Spr = KitArt.CreateSprite(((Component)((KitBoss)m_god).Arena).transform, Lib.Sheet, "DrownedFaceAppear", 0, val, (Anchor)7, true, 7f);
				Decals.Play(face.Spr, Lib["DrownedFaceAppear"]);
				face.LoopAt = now + 0.5f;
				face.Pupils = KitArt.CreateSprite(((Component)face.Spr).transform, Lib.Sheet, face.Real ? "DrownedPupilsReal" : "DrownedPupilsFalse", 1, val, (Anchor)7, false, 0f);
				((Component)face.Pupils).transform.localPosition = new Vector3(0f, 0f, -0.05f);
				((Component)face.Pupils).gameObject.SetActive(false);
				if (!face.Real)
				{
					Face face2 = face;
					Hittable val2 = Hittable.Create((Transform)null, "DrownedFalseFace", ((KitBoss)m_god).World(new Vector2(face.SlotX, 33f)), new Vector2(40f, 26f), (eAllowedDamageSource)2, (Action<Hittable, DamageInfo>)delegate(Hittable hit, DamageInfo info)
					{
						OnFalseHit(face2, info);
					}, true, 14, 1f);
					val2.FlashOnHit = false;
					val2.MinGap = 0.12f;
					val2.SetActive(false);
					((KitBoss)m_god).TrackRoot(((Component)val2).gameObject);
					face.Hit = val2;
				}
				m_faces.Add(face);
			}
			PickBotSlot();
			m_realHitAt = float.NegativeInfinity;
			m_nextPupil = now;
			KitSelfTest.Note("dream: real face in slot " + RealSlot);
		}

		public void RealStruck(float now)
		{
			m_realHitAt = now;
		}

		private bool SameSwing(float at)
		{
			return Mathf.Abs(at - m_realHitAt) <= 0.1f;
		}

		private void OnFalseHit(Face f, DamageInfo info)
		{
			if (!f.Gone && Active && KitHealth.IsHeroHit(info))
			{
				if (SameSwing(m_god.Now))
				{
					KitSelfTest.Note("false face reached by the swing that struck the real face: ignored");
				}
				else if (f.PendingAt < 0f)
				{
					f.PendingAt = m_god.Now;
				}
			}
		}

		private void Burst(Face f)
		{
			f.Gone = true;
			f.PendingAt = -1f;
			Decals.Play(f.Spr, Lib["DrownedFaceBurst"]);
			f.KillAt = m_god.Now + 0.5f;
			if ((Object)(object)f.Pupils != (Object)null)
			{
				((Component)f.Pupils).gameObject.SetActive(false);
			}
			if ((Object)(object)f.Hit != (Object)null)
			{
				f.Hit.SetActive(false);
			}
			DrownedCues.Play(DrownedCues.FalseBurst, ((Component)f.Spr).transform);
			m_god.FalseFaceBurst();
			PickBotSlot();
			KitSelfTest.Note("false face burst");
		}

		private void PickBotSlot()
		{
			List<int> list = new List<int>();
			for (int i = 0; i < m_faces.Count; i++)
			{
				if (!m_faces[i].Gone)
				{
					list.Add(i);
				}
			}
			BotSlot = ((list.Count > 0) ? list[Random.Range(0, list.Count)] : RealSlot);
		}

		public void Tick(float now, Vector2? heroFeet)
		{
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			bool flag = false;
			foreach (Face face in m_faces)
			{
				if ((Object)(object)face.Spr == (Object)null)
				{
					continue;
				}
				if (face.KillAt > 0f && now >= face.KillAt)
				{
					Decals.Kill(face.Spr);
					face.Spr = null;
					continue;
				}
				if (face.PendingAt >= 0f && !face.Gone && Active)
				{
					if (SameSwing(face.PendingAt))
					{
						face.PendingAt = -1f;
						KitSelfTest.Note("false face reached by the swing that struck the real face: ignored");
					}
					else if (now >= face.PendingAt + 0.1f)
					{
						Burst(face);
						continue;
					}
				}
				if (!face.Gone && Active && !face.Looping && now >= face.LoopAt)
				{
					face.Looping = true;
					flag = true;
					Decals.Play(face.Spr, Lib["DrownedFaceLoop"]);
					if ((Object)(object)face.Pupils != (Object)null)
					{
						((Component)face.Pupils).gameObject.SetActive(true);
					}
					if ((Object)(object)face.Hit != (Object)null)
					{
						face.Hit.SetActive(true);
					}
				}
			}
			if (flag && Active && !Revealed)
			{
				Revealed = true;
				m_god.FacesRevealed();
			}
			if (Active && heroFeet.HasValue && now >= m_nextPupil)
			{
				m_nextPupil = now + 0.1f;
				foreach (Face face2 in m_faces)
				{
					if (face2.Real && !face2.Gone && (Object)(object)face2.Pupils != (Object)null && ((Component)face2.Pupils).gameObject.activeSelf)
					{
						Decals.Frame(face2.Pupils, Lib.Sheet, "DrownedPupilsReal", PupilFrame(face2.SlotX, heroFeet.Value));
					}
				}
			}
			if (!Active)
			{
				m_faces.RemoveAll((Face f) => (Object)(object)f.Spr == (Object)null);
			}
		}

		public static int PupilFrame(float slotX, Vector2 hero)
		{
			//IL_0000: 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)
			float num = hero.x - slotX;
			if (Mathf.Abs(num) < 12f)
			{
				return 1;
			}
			if (hero.y >= 14f)
			{
				if (!(num < 0f))
				{
					return 2;
				}
				return 0;
			}
			if (!(num < 0f))
			{
				return 4;
			}
			return 3;
		}

		public void End(float now)
		{
			if (!Active)
			{
				return;
			}
			Active = false;
			Revealed = false;
			foreach (Face face in m_faces)
			{
				if ((Object)(object)face.Hit != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)face.Hit).gameObject);
					face.Hit = null;
				}
				if ((Object)(object)face.Pupils != (Object)null)
				{
					Decals.Kill(face.Pupils);
					face.Pupils = null;
				}
				if ((Object)(object)face.Spr != (Object)null && !face.Gone)
				{
					face.Gone = true;
					Decals.Play(face.Spr, Lib["DrownedFaceFade"]);
					face.KillAt = now + 0.4f;
				}
			}
		}

		public void Clear()
		{
			Active = false;
			Revealed = false;
			foreach (Face face in m_faces)
			{
				if ((Object)(object)face.Hit != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)face.Hit).gameObject);
				}
				Decals.Kill(face.Spr);
			}
			m_faces.Clear();
		}

		public Vector2 BotTargetLocal()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			return new Vector2(SlotX(BotSlot), 33f);
		}
	}
	public sealed class DrownedGod : KitBoss
	{
		internal enum Mode
		{
			Intro,
			Normal,
			Stare,
			Dream,
			Rearing,
			Over
		}

		internal static DrownedGod Active;

		internal Mode Current;

		internal float Now;

		internal readonly Madness Mad = new Madness();

		internal Temple Temple;

		internal Strikes Strikes;

		internal Gaze Gaze;

		internal Dream Faces;

		internal Lies Lies;

		internal DrownedStations Traps;

		private MadnessView m_view;

		private GodBody m_god;

		private Coroutine m_action;

		private bool m_acting;

		private Coroutine m_rear;

		private Coroutine m_gloat;

		private int m_pendingPhase;

		private float m_freeAt;

		private float m_rakeReady;

		private float m_handReady;

		private float m_gazeDue;

		private float m_eyesShutUntil;

		private float m_dreamEnd;

		private float m_lastHurt = -10f;

		private bool m_fightStarted;

		internal GameObject BodyObject
		{
			get
			{
				if (m_god == null || !((Object)(object)m_god.Body != (Object)null))
				{
					return null;
				}
				return ((Component)m_god.Body).gameObject;
			}
		}

		protected override Vector2 BarLocal => new Vector2(0f, 102f);

		internal float GodX
		{
			get
			{
				//IL_0028: Unknown result type (might be due to invalid IL or missing references)
				//IL_002d: Unknown result type (might be due to invalid IL or missing references)
				if (m_god == null || !((Object)(object)m_god.Body != (Object)null))
				{
					return 0f;
				}
				return ((KitBoss)this).RoomLocal(m_god.WorldPos).x;
			}
		}

		private float HandCooldown
		{
			get
			{
				if (((KitBoss)this).Phase < 3)
				{
					if (((KitBoss)this).Phase != 2)
					{
						return 5f;
					}
					return 4f;
				}
				return 3.5f;
			}
		}

		private int HandCount
		{
			get
			{
				if (((KitBoss)this).Phase < 2)
				{
					return 1;
				}
				return 3;
			}
		}

		private float GazeEvery
		{
			get
			{
				if (((KitBoss)this).Phase < 2)
				{
					return 11f;
				}
				return 9f;
			}
		}

		protected override void BuildArena(Room room)
		{
			Temple = new Temple(this);
			Strikes = new Strikes(this);
			Gaze = new Gaze(this);
			Faces = new Dream(this);
			Lies = new Lies(this);
			Traps = new DrownedStations(this);
			m_view = new MadnessView(this);
			Temple.Build(room);
			Traps.Spawn();
			Lies.Attach(Traps.Seat);
			Lies.CreateReticle();
			m_view.Create();
		}

		protected override KitBody SpawnBodies(Room room)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			KitBody val = KitBodies.Spawn<KitBrain>((KitBoss)(object)this, DrownedTemplates.BodyTemplate, new Vector2(0f, 44f), "DrownedGod");
			val.SetHurtSound((AudioCue)null, 0.25f);
			val.RefuseStatuses = true;
			val.Damaged += OnGodDamaged;
			m_god = new GodBody(val, DrownedTemplates.Body);
			m_god.SetZone(GodBody.Zone.Chest);
			try
			{
				m_god.AddWings();
			}
			catch (Exception ex)
			{
				((KitBoss)this).Ctx.Log.Error("The wings could not be drawn (the fight goes on without them): " + ex);
			}
			Active = this;
			Mad.Frozen = true;
			Mad.Set(0f, Now);
			return val;
		}

		protected override IEnumerator Intro()
		{
			Current = Mode.Intro;
			yield return KitBoss.WaitGameTime(0.6f);
			if (m_god != null && m_god.Alive)
			{
				m_god.Act("DrownedAwaken", DrownedCues.Awaken);
			}
			yield return KitBoss.WaitGameTime(0.6f);
			Mad.Frozen = false;
			Mad.Set(20f, Now);
			m_view.Show(on: true);
			KitSelfTest.Note("glance: madness " + Mad.Value);
			yield return KitBoss.WaitGameTime(0.19999999f);
			if (m_god != null && m_god.Alive)
			{
				m_god.Act("DrownedRoar", DrownedCues.Roar);
			}
			yield return KitBoss.WaitGameTime(1.6f);
			if (m_god != null && m_god.Alive)
			{
				m_god.Release();
			}
		}

		protected override void OnFightStart()
		{
			m_fightStarted = true;
			Current = Mode.Normal;
			m_freeAt = Now;
			m_rakeReady = Now;
			m_handReady = Now + 2f;
			m_gazeDue = Now + 4f;
			m_eyesShutUntil = Now;
			m_view.Show(on: true);
		}

		protected override void KitUpdate()
		{
			//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_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: 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_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0224: Unknown result type (might be due to invalid IL or missing references)
			float deltaTime = Time.deltaTime;
			Now += deltaTime;
			if (m_god == null)
			{
				return;
			}
			m_god.TickWings();
			m_god.LockFlip(Current == Mode.Dream);
			Player val = Util.Hero();
			bool flag = (Object)(object)val != (Object)null && (Object)(object)val.GetHealthComponent() != (Object)null && val.GetHealthComponent().IsAlive();
			Vector2? val2 = (flag ? new Vector2?(((KitBoss)this).RoomLocal(((Component)val).transform.position)) : ((Vector2?)null));
			Temple.Tick(Now);
			Faces.Tick(Now, val2);
			Lies.Tick(Now, deltaTime);
			Traps.Tick(Now);
			if (!((KitBoss)this).Fighting || !m_fightStarted || !m_god.Alive)
			{
				return;
			}
			Strikes.Tick(Now, val2);
			bool flag2 = Gaze.Tick(Now, (Vector2)(((??)val2) ?? new Vector2(9999f, 9999f)));
			m_god.KeepOnTrack(((Component)((KitBoss)this).Arena).transform.position);
			if (flag)
			{
				float num = 0f;
				if (flag2)
				{
					num += 40f;
				}
				if (Temple.InWater(val2.Value, Now))
				{
					num += 10f;
				}
				Mad.Tick(deltaTime, Now, num, Temple.InCleanSign(val2.Value));
			}
			if (Current == Mode.Rearing || Current == Mode.Over || Current == Mode.Intro)
			{
				return;
			}
			if (Current != Mode.Dream && Mad.Value >= 80f)
			{
				BeginDream();
				return;
			}
			if (Current == Mode.Dream && Now >= m_dreamEnd)
			{
				EndDream();
			}
			if (!flag)
			{
				m_god.Stop();
			}
			else
			{
				Think(val2.Value);
			}
		}

		protected override void KitLateUpdate()
		{
			if (m_god != null)
			{
				m_god.PlaceZone();
			}
			if (m_view != null)
			{
				m_view.Update(Mad, Util.Hero());
			}
		}

		private void Think(Vector2 hero)
		{
			//IL_00e8: 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_0087: 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)
			if (m_acting || !m_god.Alive)
			{
				return;
			}
			float godX = GodX;
			bool flag = Now >= m_freeAt && m_god.Free;
			if (Current == Mode.Normal)
			{
				if (flag)
				{
					if (Mad.Value >= 40f && Now >= m_eyesShutUntil)
					{
						RunAction(StareRoutine());
						return;
					}
					if (Now >= m_rakeReady && InFrontZone(hero, godX))
					{
						RunAction(RakeAction());
						return;
					}
					if (Now >= m_gazeDue)
					{
						RunAction(GazeAction(hero));
						return;
					}
					if (Now >= m_handReady)
					{
						RunAction(HandAction());
						return;
					}
				}
				if (m_god.Free)
				{
					m_god.Drift(godX, hero.x);
				}
			}
			else
			{
				if (Current != Mode.Dream)
				{
					return;
				}
				if (flag)
				{
					if (Now >= m_rakeReady && InFrontZone(hero, godX))
					{
						RunAction(RakeAction());
						return;
					}
					if (Now >= m_handReady)
					{
						RunAction(HandAction());
						return;
					}
				}
				m_god.Stop();
			}
		}

		private static bool InFrontZone(Vector2 hero, float godX)
		{
			//IL_0000: 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)
			if (hero.y > -12f)
			{
				return Mathf.Abs(hero.x - godX) <= 70f;
			}
			return false;
		}

		private static IEnumerable Pause(float seconds)
		{
			float left = seconds;
			while (left > 0f)
			{
				yield return null;
				if (!SystemTime.Paused)
				{
					left -= Time.deltaTime;
				}
			}
		}

		private void RunAction(IEnumerator routine)
		{
			m_acting = true;
			m_god.Stop();
			m_action = ((MonoBehaviour)this).StartCoroutine(ActionShell(routine));
		}

		private IEnumerator ActionShell(IEnumerator routine)
		{
			while (true)
			{
				object current;
				try
				{
					if (!routine.MoveNext())
					{
						break;
					}
					current = routine.Current;
					goto IL_006c;
				}
				catch (Exception ex)
				{
					((KitBoss)this).Ctx.Log.Error("A god action failed, the god returns to idle: " + ex);
					SafeRecover();
				}
				break;
				IL_006c:
				yield return current;
			}
			m_acting = false;
			m_action = null;
			m_freeAt = Now + 0.4f;
		}

		private void AbortAction()
		{
			if (m_action != null)
			{
				((MonoBehaviour)this).StopCoroutine(m_action);
				m_action = null;
			}
			m_acting = false;
			Strikes.ClearArc();
			Gaze.ClearTelegraph();
			if (Current == Mode.Stare)
			{
				FaceUpState();
				Current = Mode.Normal;
			}
		}

		private void SafeRecover()
		{
			try
			{
				Strikes.ClearArc();
				Gaze.ClearTelegraph();
				if (Current == Mode.Stare)
				{
					FaceUpState();
					Current = Mode.Normal;
				}
				m_god.Release();
			}
			catch (Exception ex)
			{
				((KitBoss)this).Ctx.Log.WarnOnce("recover", ex);
			}
		}

		private IEnumerable RakeSteps()
		{
			Player val = Util.Hero();
			float godX = GodX;
			if ((Object)(object)val != (Object)null && Current != Mode.Dream)
			{
				m_god.Face(((KitBoss)this).RoomLocal(((Component)val).transform.position).x - godX);
			}
			m_god.Act("DrownedRakeRaise", DrownedCues.RakeRaise);
			Strikes.RakeTelegraph(godX);
			foreach (object item in Pause(0.7f))
			{
				yield return item;
			}
			m_god.Act("DrownedRakeSweep", DrownedCues.Rake);
			foreach (object item2 in Pause(0.1f))
			{
				yield return item2;
			}
			Strikes.RakeStrike(godX);
			m_rakeReady = Now + 3.5f;
			foreach (object item3 in Pause(0.3f))
			{
				yield return item3;
			}
		}

		private IEnumerator RakeAction()
		{
			foreach (object item in RakeSteps())
			{
				yield return item;
			}
			m_god.Release();
		}

		private IEnumerator HandAction()
		{
			m_god.Act("DrownedHandPlunge");
			foreach (object item in Pause(0.5f))
			{
				yield return item;
			}
			m_handReady = Now + HandCooldown;
			Strikes.QueueHands(HandCount, Now);
			m_god.Release();
		}

		private unsafe IEnumerator GazeAction(Vector2 flarePoint)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			m_gazeDue = Now + GazeEvery;
			m_god.Act("DrownedGazeFlare", DrownedCues.Gaze);
			Gaze.Telegraph(flarePoint, ((KitBoss)this).Phase >= 3, Now + 0.8f);
			Vector2 val = flarePoint;
			KitSelfTest.Note("gaze at " + ((object)(*(Vector2*)(&val))/*cast due to .constrained prefix*/).ToString());
			foreach (object item in Pause(0.8f))
			{
				yield return item;
			}
			m_god.Release();
		}

		private void FaceDownState()
		{
			m_god.SetVulnerableMult((((KitBoss)this).Phase >= 3) ? 6f : 4.5f);
			m_god.SetZone(GodBody.Zone.Face);
			m_god.Body.HoldVulnerable = true;
		}

		private void FaceUpState()
		{
			Mad.FaceDown = false;
			m_god.Body.HoldVulnerable = false;
			m_god.SetZone(GodBody.Zone.Chest);
		}

		private IEnumerator StareRoutine()
		{
			Current = Mode.Stare;
			Mad.FaceDown = true;
			Gaze.FadeAll();
			float left = ((((KitBoss)this).Phase >= 3) ? 4f : 5f);
			KitSelfTest.Note("stare start (madness " + Mad.Value.ToString("0") + ")");
			DrownedCues.Play(DrownedCues.Seeing, m_god.Transform);
			FaceDownState();
			m_god.Act("DrownedStareDown", DrownedCues.Stare);
			float down = 0.6f;
			bool looping = false;
			bool faceUpAlready = false;
			while (true)
			{
				yield return null;
				if (SystemTime.Paused)
				{
					continue;
				}
				float deltaTime = Time.deltaTime;
				left -= deltaTime;
				if (!looping)
				{
					down -= deltaTime;
					if (down <= 0f)
					{
						looping = true;
						m_god.Act("DrownedStareLoop");
					}
				}
				if (left <= 0f || Mad.Value < 40f)
				{
					break;
				}
				Player val = Util.Hero();
				if (!looping || !((Object)(object)val != (Object)null) || !(Mad.Value >= 60f) || !(Now >= m_rakeReady) || !InFrontZone(((KitBoss)this).RoomLocal(((Component)val).transform.position), GodX))
				{
					continue;
				}
				m_god.Body.HoldVulnerable = false;
				m_god.SetZone(GodBody.Zone.Chest);
				KitSelfTest.Note("stare paused for a rake");
				foreach (object item in RakeSteps())
				{
					yield return item;
				}
				if (Mad.Value < 40f)
				{
					faceUpAlready = true;
					break;
				}
				FaceDownState();
				m_god.Act("DrownedStareDown", DrownedCues.Stare);
				down = 0.6f;
				looping = false;
			}
			KitSelfTest.Note("stare end (madness " + Mad.Value.ToString("0") + ")");
			FaceUpState();
			if (!faceUpAlready)
			{
				m_god.Act("DrownedStareUp");
				foreach (object item2 in Pause(0.5f))
				{
					yield return item2;
				}
			}
			m_eyesShutUntil = Now + 3f;
			Current = Mode.Normal;
			m_god.Release();
		}

		private void BeginDream()
		{
			if (Current != Mode.Dream && Current != Mode.Rearing && Current != Mode.Over)
			{
				AbortAction();
				Gaze.FadeAll();
				Current = Mode.Dream;
				Mad.Set(80f, Now);
				Mad.Frozen = true;
				Mad.FaceDown = false;
				m_god.Stop();
				m_god.Release();
				Temple.SetDreamTint(on: true);
				DrownedCues.Play(DrownedCues.Dream, m_god.Transform);
				DrownedCues.Play(DrownedCues.FacesAppear, m_god.Transform);
				Faces.Begin(Now);
				m_god.SetVulnerableMult(3f);
				m_god.LockFlip(locked: true);
				m_god.SetZone(GodBody.Zone.DreamFace, Faces.SlotX(Faces.RealSlot), GodX, live: false);
				m_god.Body.HoldVulnerable = true;
				Strikes.RaiseTelegraphs();
				Lies.RaiseTelegraphs();
				m_dreamEnd = Now + ((((KitBoss)this).Phase >= 3) ? 3f : 4f);
				m_freeAt = Now + 0.4f;
			}
		}

		internal void FacesRevealed()
		{
			if (Current == Mode.Dream && m_god != null && m_god.Alive)
			{
				m_god.SetZoneLive(live: true);
				KitSelfTest.Note("dream faces revealed");
			}
		}

		private void EndDream()
		{
			Faces.End(Now);
			Temple.SetDreamTint(on: false);
			m_god.Body.HoldVulnerable = false;
			m_god.SetZone(GodBody.Zone.Chest);
			m_god.LockFlip(locked: false);
			Mad.Frozen = false;
			Mad.Set(0f, Now);
			DrownedCues.Play(DrownedCues.Wake, m_god.Transform);
			Current = Mode.Normal;
			m_eyesShutUntil = Now;
			KitSelfTest.Note("dream end");
		}

		internal void FalseFaceBurst()
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			Player val = Util.Hero();
			if ((Object)(object)val != (Object)null)
			{
				Strikes.HandAt(((KitBoss)this).RoomLocal(((Component)val).transform.position), Now);
			}
		}

		private void OnGodDamaged(DamageInfo info)
		{
			if (info != null && !info.m_isDamageFromStatus && KitHealth.IsHeroHit(info))
			{
				if (Faces.Active)
				{
					Faces.RealStruck(Now);
				}
				if (((KitBoss)this).Fighting && Current != Mode.Dream && Current != Mode.Rearing)
				{
					Mad.Blow(Now);
				}
				if (Now - m_lastHurt >= 0.25f)
				{
					m_lastHurt = Now;
					DrownedCues.Play((m_god != null && m_god.Body.HoldVulnerable) ? DrownedCues.Hurt : DrownedCues.VeilHit, (m_god != null) ? m_god.Transform : ((Component)this).transform);
				}
			}
		}

		internal void WhisperOnHero()
		{
			if (((KitBoss)this).Fighting && Current != Mode.Rearing)
			{
				Mad.Add(14f, Now);
				KitSelfTest.Note("whisper on hero (madness " + Mad.Value.ToString("0") + ")");
			}
		}

		internal void SpawnWhisperPop(Vector2 at)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				exSprite obj = Decals.Make(this, DrownedTemplates.Env, "DrownedWhisperPop", at + new Vector2(0f, 18f), (Anchor)4, -9f);
				Decals.Play(obj, DrownedTemplates.Env["DrownedWhisperPop"]);
				Object.Destroy((Object)(object)((Component)obj).gameObject, DrownedTemplates.Env["DrownedWhisperPop"].length + 0.05f);
			}
			catch (Exception ex)
			{
				((KitBoss)this).Ctx.Log.WarnOnce("whisper pop", ex);
			}
		}

		protected override void OnPhase(int phase)
		{
			if (Current != Mode.Over)
			{
				if (Current == Mode.Rearing)
				{
					m_pendingPhase = Mathf.Max(m_pendingPhase, phase);
				}
				else
				{
					m_rear = ((MonoBehaviour)this).StartCoroutine(RearRoutine(phase));
				}
			}
		}

		private void ClearFightObjects(bool drainFloods)
		{
			Strikes.ClearAll();
			Gaze.FadeAll();
			Lies.ClearAll();
			Traps.ClearPending();
			WhisperMark.PopAll(this);
			if (drainFloods)
			{
				Temple.DrainAll(Now);
			}
		}

		private IEnumerator RearRoutine(int phase)
		{
			bool num = Current == Mode.Dream;
			AbortAction();
			Current = Mode.Rearing;
			if ((Object)(object)((KitBoss)this).LifeHealth != (Object)null)
			{
				((KitBoss)this).LifeHealth.StartInvincibility("DrownedPhase");
			}
			((KitBoss)this).SetStationsSuspended(true);
			if (num)
			{
				Faces.End(Now);
				Temple.SetDreamTint(on: false);
			}
			FaceUpState();
			ClearFightObjects(drainFloods: true);
			Temple.CleanseAll(Now);
			Mad.Frozen = false;
			Mad.Set(20f, Now);
			Mad.Frozen = true;
			KitSelfTest.Note("rear-up " + phase);
			m_god.Act("DrownedRearUp", DrownedCues.Rear);
			foreach (object item in Pause(0.8f))
			{
				yield return item;
			}
			m_god.Act("DrownedRearLoop");
			try
			{
				ArenaChange(phase);
			}
			catch (Exception ex)
			{
				((KitBoss)this).Ctx.Log.Error("Phase " + phase + " arena change failed: " + ex);
			}
			foreach (object item2 in Pause(1.4f))
			{
				yield return item2;
			}
			m_god.Act("DrownedRearDown");
			foreach (object item3 in Pause(0.6f))
			{
				yield return item3;
			}
			m_god.Act("DrownedRoar", DrownedCues.Roar);
			foreach (object item4 in Pause(1.6f))
			{
				yield return item4;
			}
			m_god.Release();
			if ((Object)(object)((KitBoss)this).LifeHealth != (Object)null)
			{
				((KitBoss)this).LifeHealth.StopInvincibility("DrownedPhase");
			}
			((KitBoss)this).SetStationsSuspended(false);
			Mad.Frozen = false;
			Current = Mode.Normal;
			m_rakeReady = Now + 1.75f;
			m_handReady = Now + HandCooldown * 0.5f;
			m_gazeDue = Now + 3f;
			m_eyesShutUntil = Now;
			m_freeAt = Now + 0.4f;
			m_rear = null;
			if (m_pendingPhase > phase)
			{
				int pendingPhase = m_pendingPhase;
				m_pendingPhase = 0;
				m_rear = ((MonoBehaviour)this).StartCoroutine(RearRoutine(pendingPhase));
			}
		}

		private void ArenaChange(int phase)
		{
			if (phase == 2)
			{
				m_god.SpreadWings();
				Traps.WakeFront();
			}
			else if (phase >= 3)
			{
				Temple.StartOverflow();
				Temple.Crack(0);
				Temple.Crack(1);
			}
		}

		private void StopRoutines()
		{
			if (m_action != null)
			{
				((MonoBehaviour)this).StopCoroutine(m_action);
				m_action = null;
			}
			m_acting = false;
			if (m_rear != null)
			{
				((MonoBehaviour)this).StopCoroutine(m_rear);
				m_rear = null;
			}
			if (m_gloat != null)
			{
				((MonoBehaviour)this).StopCoroutine(m_gloat);
				m_gloat = null;
			}
		}

		protected override void OnBossDying(DamageInfo info)
		{
			StopRoutines();
			Current = Mode.Over;
			Mad.Frozen = true;
			try
			{
				Faces.Clear();
				Temple.SetDreamTint(on: false);
				Temple.ClearGlow();
				ClearFightObjects(drainFloods: true);
				Lies.HideReticle();
				if (m_view != null)
				{
					m_view.Show(on: false);
				}
				if (m_god != null)
				{
					m_god.Body.HoldVulnerable = false;
					m_god.FoldWings();
				}
			}
			catch (Exception ex)
			{
				((KitBoss)this).Ctx.Log.WarnOnce("dying cleanup", ex);
			}
			KitSelfTest.Note("the god dies");
		}

		protected override void OnHeroKilledKit(Player hero)
		{
			StopRoutines();
			bool flag = Current == Mode.Dream;
			Current = Mode.Over;
			Mad.Frozen = true;
			Mad.FaceDown = false;
			try
			{
				Faces.Clear();
				Temple.SetDreamTint(on: false);
				Temple.ClearGlow();
				ClearFightObjects(drainFloods: false);
				Lies.HideReticle();
				if (m_view != null)
				{
					m_view.Show(on: false);
				}
				if (m_god != null && m_god.Alive)
				{
					m_god.Body.HoldVulnerable = false;
					m_god.SetZone(GodBody.Zone.Chest);
					m_gloat = ((MonoBehaviour)this).StartCoroutine(Gloat());
				}
			}
			catch (Exception ex)
			{
				((KitBoss)this).Ctx.Log.WarnOnce("gloat", ex);
			}
			if (flag)
			{
				KitSelfTest.Note("hero killed in the Dream");
			}
		}

		private IEnumerator Gloat()
		{
			m_god.Act("DrownedRoar", DrownedCues.Roar);
			foreach (object item in Pause(1.6f))
			{
				yield return item;
			}
			if (m_god != null && m_god.Alive)
			{
				m_god.Act("DrownedIdleSeeing");
			}
			m_gloat = null;
		}

		protected override void OnFrozen(bool frozen)
		{
			if (frozen)
			{
				if (Current != Mode.Over)
				{
					bool num = Current == Mode.Dream;
					AbortAction();
					if (num)
					{
						EndDream();
					}
					if (m_god != null)
					{
						m_god.Stop();
						m_god.Release();
					}
					if (m_view != null)
					{
						m_view.Show(on: false);
					}
					Lies.HideReticle();
				}
			}
			else if (m_view != null && Current != Mode.Over && m_fightStarted)
			{
				m_view.Show(on: true);
			}
		}

		protected override void OnCleanup()
		{
			try
			{
				if (m_view != null)
				{
					m_view.Destroy();
				}
				if (Faces != null)
				{
					Faces.Clear();
				}
			}
			catch (Exception ex)
			{
				((KitBoss)this).Ctx.Log.WarnOnce("cleanup", ex);
			}
			if ((Object)(object)Active == (Object)(object)this)
			{
				Active = null;
			}
		}

		public override bool GetVulnerable()
		{
			if (!((KitBoss)this).Fighting || m_god == null || !m_god.Alive)
			{
				return false;
			}
			if (Current == Mode.Dream || (Current == Mode.Stare && m_god.Body.HoldVulnerable))
			{
				return true;
			}
			PlayerData heroPlayerData = SystemLevel.GetHeroPlayerData();
			if (Current == Mode.Normal && heroPlayerData != null)
			{
				return heroPlayerData.IsBot;
			}
			return false;
		}

		protected override Vector2 BotTarget()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			if (m_god == null || !m_god.Alive)
			{
				return Vector2.op_Implicit(((Component)this).transform.position);
			}
			float godX = GodX;
			Vector2 val = default(Vector2);
			if (Current == Mode.Dream)
			{
				val = Faces.BotTargetLocal();
			}
			else if (Current == Mode.Stare)
			{
				((Vector2)(ref val))..ctor(godX, 30f);
			}
			else
			{
				((Vector2)(ref val))..ctor(godX, 30f);
			}
			return Vector2.op_Implicit(((KitBoss)this).World(val));
		}
	}
	internal sealed class DrownedStations
	{
		private sealed class PendingFlood
		{
			public KitStation Station;

			public int Side;

			public float At;
		}

		private readonly DrownedGod m_god;

		public readonly List<KitStation> Idols = new List<KitStation>();

		public readonly List<KitStation> FrontIdols = new List<KitStation>();

		public readonly KitStation[] Sluices = (KitStation[])(object)new KitStation[2];

		public KitStation Seat;

		private readonly List<PendingFlood> m_floods = new List<PendingFlood>();

		private readonly Dictionary<KitStation, Vector2> m_local = new Dictionary<KitStation, Vector2>();

		private bool m_frontAwake;

		private static readonly Collider[] s_overlap = (Collider[])(object)new Collider[16];

		private static readonly RaycastHit[] s_hits = (RaycastHit[])(object)new RaycastHit[16];

		public DrownedStations(DrownedGod god)
		{
			m_god = god;
		}

		public void Spawn()
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: 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_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: 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_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_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Expected O, but got Unknown
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			SpawnIdol(new Vector2(-121f, 24f), front: false);
			SpawnIdol(new Vector2(121f, 24f), front: false);
			SpawnIdol(new Vector2(-116f, -46f), front: true);
			SpawnIdol(new Vector2(116f, -46f), front: true);
			Sluices[0] = SpawnSluice(new Vector2(-100f, 50f), 0, new float[2] { 270f, 330f });
			Sluices[1] = SpawnSluice(new Vector2(100f, 50f), 1, new float[2] { 270f, 210f });
			Seat = ((KitBoss)m_god).SpawnStation(DrownedTemplates.SeatT, new Vector2(0f, -48f), new StationSpec
			{
				Kind = "Seat",
				HumanOnly = true,
				DrawnSeatLocal = new Vector2(0f, 24f),
				ActionCentreLocal = new Vector2(0f, 17f),
				BlockerLocal = new Rect(-12f, 0f, 24f, 8f),
				ExitAfterIdle = 2.5f
			});
			m_local[Seat] = new Vector2(0f, -48f);
		}

		private void SpawnIdol(Vector2 at, bool front)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0068: 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_007f: 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_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Expected O, but got Unknown
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			float value = Mathf.Repeat(Mathf.Atan2(0f - at.y, 0f - at.x) * 57.29578f, 360f);
			KitStation val = ((KitBoss)m_god).SpawnStation(DrownedTemplates.IdolT, at, new StationSpec
			{
				Kind = (front ? "IdolFront" : "IdolBack"),
				WakePhase = ((!front) ? 1 : 2),
				WakeByBoss = front,
				DimWhenDormant = !front,
				AimInitial = value,
				DrawnSeatLocal = new Vector2(0f, 26f),
				ActionCentreLocal = new Vector2(0f, 19f),
				BlockerLocal = new Rect(-10f, 0f, 20f, 8f),
				ExitAfterIdle = 2.5f,
				CanHit = IdolCanHit,
				ShouldEnter = IdolShouldEnter,
				BotAim = IdolBotAim
			});
			m_local[val] = at;
			val.Fired += delegate(KitStation s)
			{
				DrownedCues.Play(DrownedCues.Whisper, ((Component)s).transform);
			};
			Idols.Add(val);
			if (front)
			{
				FrontIdols.Add(val);
			}
		}

		private KitStation SpawnSluice(Vector2 at, int side, float[] angles)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: 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_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: 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_0083: 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_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Expected O, but got Unknown
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			KitStation val = ((KitBoss)m_god).SpawnStation(DrownedTemplates.SluiceT, at, new StationSpec
			{
				Kind = ((side == 0) ? "SluiceL" : "SluiceR"),
				AimInitial = 270f,
				DrawnSeatLocal = new Vector2(0f, 9f),
				ActionCentreLocal = new Vector2(0f, 17f),
				ExitAfterIdle = 2.5f,
				CanHit = SluiceCanHit,
				ShouldEnter = SluiceShouldEnter,
				BotAim = SluiceBotAim
			});
			Util.Set((object)val.Trap, "m_attackAnglesList", (object)angles);
			m_local[val] = at;
			val.Fired += delegate(KitStation s)
			{
				OnSluice(s, side);
			};
			return val;
		}

		private int SideOf(KitStation st)
		{
			return ((Object)(object)st == (Object)(object)Sluices[1]) ? 1 : 0;
		}

		private static bool SluiceReady(KitStation st)
		{
			Attacks val = (((Object)(object)st.Trap != (Object)null) ? st.Trap.GetAttackComponent() : null);
			if (val != null)
			{
				return val.CanAttack(false);
			}
			return false;
		}

		private bool FloodPending(KitStation st)
		{
			foreach (PendingFlood flood in m_floods)
			{
				if ((Object)(object)flood.Station == (Object)(object)st)
				{
					return true;
				}
			}
			return false;
		}

		private void OnSluice(KitStation st, int side)
		{
			DrownedCues.Play(DrownedCues.Sluice, ((Component)st).transform);
			m_floods.Add(new PendingFlood
			{
				Station = st,
				Side = side,
				At = m_god.Now + 0.16f
			});
		}

		public void Tick(float now)
		{
			for (int num = m_floods.Count - 1; num >= 0; num--)
			{
				PendingFlood pendingFlood = m_floods[num];
				if (!(now < pendingFlood.At))
				{
					m_floods.RemoveAt(num);
					if (!((Object)(object)pendingFlood.Station == (Object)null))
					{
						if (!((KitBoss)m_god).Fighting || m_god.Current == DrownedGod.Mode.Rearing || m_god.Current == DrownedGod.Mode.Over)
						{
							pendingFlood.Station.RefundCooldown();
						}
						else
						{
							m_god.Temple.LaneFor(pendingFlood.Side, pendingFlood.Station.AimDegrees).Flood(now);
						}
					}
				}
			}
			for (int i = 0; i < 2; i++)
			{
				KitStation val = Sluices[i];
				if (!((Object)(object)val == (Object)null))
				{
					Lane lane = ((val.Occupant != null && ((KitBoss)m_god).Fighting && (SluiceReady(val) || FloodPending(val))) ? m_god.Temple.LaneFor(i, val.AimDegrees) : null);
					m_god.Temple.Lanes[i * 2].SetGlow(lane == m_god.Temple.Lanes[i * 2]);
					m_god.Temple.Lanes[i * 2 + 1].SetGlow(lane == m_god.Temple.Lanes[i * 2 + 1]);
				}
			}
			if (m_frontAwake)
			{
				return;
			}
			foreach (KitStation frontIdol in FrontIdols)
			{
				if (!((Object)(object)frontIdol == (Object)null) && frontIdol.Dormant)
				{
					exSpriteAnimation component = ((Component)frontIdol).GetComponent<exSpriteAnimation>();
					exSpriteAnimClip val2 = DrownedTemplates.Env["DrownedIdol_greyedOut"];
					if ((Object)(object)component != (Object)null && !component.IsPlaying(((Object)val2).name))
					{
						component.Play(val2);
					}
				}
			}
		}

		public void WakeFront()
		{
			m_frontAwake = true;
			((KitBoss)m_god).WakeStations(2);
			foreach (KitStation frontIdol in FrontIdols)
			{
				if (!((Object)(object)frontIdol == (Object)null))
				{
					exSpriteAnimation component = ((Component)frontIdol).GetComponent<exSpriteAnimation>();
					if ((Object)(object)component != (Object)null)
					{
						component.Play(DrownedTemplates.Env["DrownedIdol_inactive"]);
					}
				}
			}
			KitSelfTest.Note("front idols awake");
		}

		public void ClearPending()
		{
			foreach (PendingFlood flood in m_floods)
			{
				if ((Object)(object)flood.Station != (Object)null)
				{
					flood.Station.RefundCooldown();
				}
			}
			m_floods.Clear();
		}

		private Vector2 LocalOf(KitStation st)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			if (!m_local.TryGetValue(st, out var value))
			{
				return ((KitBoss)m_god).RoomLocal(((Component)st).transform.position);
			}
			return value;
		}

		private Vector2 ShotOrigin(KitStation st)
		{
			//IL_0002: 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_0016: Unknown result type (might be due to invalid IL or missing references)
			return LocalOf(st) + new Vector2(0f, 4f);
		}

		internal bool IdolTarget(Vector2 heroFeet, out Vector2 target, out bool isHero)
		{
			//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_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_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			target = Vector2.zero;
			isHero = false;
			if (!((KitBoss)m_god).Fighting || m_god.Current == DrownedGod.Mode.Dream || m_god.Current == DrownedGod.Mode.Rearing || m_god.Current == DrownedGod.Mode.Over)
			{
				return false;
			}
			float value = m_god.Mad.Value;
			if (value >= 80f)
			{
				return false;
			}
			if (value >= 55f && value <= 79f)
			{
				target = heroFeet + new Vector2(0f, -0.6f);
				isHero = true;
				return true;
			}
			if (value >= 30f)
			{
				float num = float.MaxValue;
				bool result = false;
				ElderSign[] signs = m_god.Temple.Signs;
				foreach (ElderSign elderSign in signs)
				{
					if (elderSign != null && elderSign.State == ElderSign.Kind.Clean)
					{
						Vector2 val = elderSign.Centre - heroFeet;
						float magnitude = ((Vector2)(ref val)).magnitude;
						if (magnitude <= 40f && magnitude < num)
						{
							num = magnitude;
							target = elderSign.Centre;
							result = true;
						}
					}
				}
				return result;
			}
			return false;
		}

		internal static bool ShotHits(Vector2 origin, float angleDeg, Vector2 target, float tol)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			//IL_0040: 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)
			float num = angleDeg * ((float)Math.PI / 180f);
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(Mathf.Cos(num), Mathf.Sin(num));
			Vector2 val2 = target - origin;
			if (Vector2.Dot(val2, val) <= 0f)
			{
				return false;
			}
			return Mathf.Abs(val2.x * val.y - val2.y * val.x) <= tol;
		}

		internal static float SnappedAngle(float exactDeg, float initialDeg)
		{
			return Mathf.Round((exactDeg - initialDeg) / 7.5f) * 7.5f + initialDeg;
		}

		private float InitialAim(KitStation st)
		{
			return st.Spec.AimInitial.GetValueOrDefault();
		}

		private bool IdolCanHit(KitStation st, Player hero)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: 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_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: 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_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			if (!IdolTarget(((KitBoss)m_god).RoomLocal(((Component)hero).transform.position), out var target, out var isHero))
			{
				return false;
			}
			Vector2 val = ShotOrigin(st);
			if (!KitGeom.LineClear(Vector2.op_Implicit(((KitBoss)m_god).World(val)), Vector2.op_Implicit(((KitBoss)m_god).World(target)), 16777728))
			{
				return false;
			}
			if (ShotHits(val, st.AimDegrees, target, isHero ? 4f : 8f))
			{
				return ShotClear(st, val, st.AimDegrees, target);
			}
			return false;
		}

		private bool IdolShouldEnter(KitStation st, Player hero)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: 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_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: 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_0062: 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_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			if (!IdolTarget(((KitBoss)m_god).RoomLocal(((Component)hero).transform.position), out var target, out var isHero))
			{
				return false;
			}
			Vector2 val = ShotOrigin(st);
			if (!KitGeom.LineClear(Vector2.op_Implicit(((KitBoss)m_god).World(val)), Vector2.op_Implicit(((KitBoss)m_god).World(target)), 16777728))
			{
				return false;
			}
			float angleDeg = SnappedAngle(Mathf.Atan2(target.y - val.y, target.x - val.x) * 57.29578f, InitialAim(st));
			if (ShotHits(val, angleDeg, target, isHero ? 4f : 8f))
			{
				return ShotClear(st, val, angleDeg, target);
			}
			return false;
		}

		private bool ShotClear(KitStation st, Vector2 o, float angleDeg, Vector2 target)
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: 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_0067: 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)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			Transform val = (((Object)(object)st.Trap != (Object)null) ? ((Component)st.Trap).transform : ((Component)st).transform);
			float num = angleDeg * ((float)Math.PI / 180f);
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(Mathf.Cos(num), Mathf.Sin(num));
			float num2 = Mathf.Max(0f, Vector2.Dot(target - o, val2));
			Vector3 val3 = ((KitBoss)m_god).World(o + new Vector2(0f, 1.04f));
			val3.z = 0f;
			Vector3 val4 = default(Vector3);
			((Vector3)(ref val4))..ctor(4.72f, 2.76f, 1f);
			int num3 = Physics.OverlapBoxNonAlloc(val3, val4, s_overlap, Quaternion.identity, 16777728, (QueryTriggerInteraction)1);
			for (int i = 0; i < num3; i++)
			{
				if ((Object)(object)s_overlap[i] != (Object)null && !((Component)s_overlap[i]).transform.IsChildOf(val))
				{
					return false;
				}
			}
			if (num2 < 0.01f)
			{
				return true;
			}
			num3 = Physics.BoxCastNonAlloc(val3, val4, new Vector3(val2.x, val2.y, 0f), s_hits, Quaternion.identity, num2, 16777728, (QueryTriggerInteraction)1);
			for (int j = 0; j < num3; j++)
			{
				if ((Object)(object)((RaycastHit)(ref s_hits[j])).collider != (Object)null && !((Component)((RaycastHit)(ref s_hits[j])).collider).transform.IsChildOf(val))
				{
					return false;
				}
			}
			return true;
		}

		private Vector2? IdolBotAim(KitStation st, Player hero)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: 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_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			if (!IdolTarget(((KitBoss)m_god).RoomLocal(((Component)hero).transform.position), out var target, out var _))
			{
				return null;
			}
			return Vector2.op_Implicit(((KitBoss)m_god).World(target + new Vector2(0f, 22f)));
		}

		private bool SluiceWants()
		{
			if (!((KitBoss)m_god).Fighting || m_god.Current == DrownedGod.Mode.Dream || m_god.Current == DrownedGod.Mode.Rearing || m_god.Current == DrownedGod.Mode.Over)
			{
				return false;
			}
			float value = m_god.Mad.Value;
			if (value >= 40f)
			{
				return value <= 79f;
			}
			return false;
		}

		internal Lane SluiceLane(int side, Vector2 heroFeet)
		{
			//IL_0039: 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_0042: 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)
			Lane lane = m_god.Temple.Lanes[side * 2];
			Lane lane2 = m_god.Temple.Lanes[side * 2 + 1];
			float now = m_god.Now;
			if (lane2.Contains(heroFeet) && !lane2.WetAt(heroFeet, now))
			{
				return lane2;
			}
			if (lane.Contains(heroFeet) && !lane.WetAt(heroFeet, now))
			{
				return lane;
			}
			return null;
		}

		private bool SluiceShouldEnter(KitStation st, Player hero)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			if (SluiceWants())
			{
				return SluiceLane(SideOf(st), ((KitBoss)m_god).RoomLocal(((Component)hero).transform.position)) != null;
			}
			return false;
		}

		private bool SluiceCanHit(KitStation st, Player hero)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: 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)
			if (!SluiceWants())
			{
				return false;
			}
			Vector2 p = ((KitBoss)m_god).RoomLocal(((Component)hero).transform.position);
			Lane lane = m_god.Temple.LaneFor(SideOf(st), st.AimDegrees);
			if (lane.Contains(p))
			{
				return !lane.WetAt(p, m_god.Now);
			}
			return false;
		}

		private Vector2? SluiceBotAim(KitStation st, Player hero)
		{
			//IL_0026: 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_0045: 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_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//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)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			if (!SluiceWants())
			{
				return null;
			}
			Lane lane = SluiceLane(SideOf(st), ((KitBoss)m_god).RoomLocal(((Component)hero).transform.position));
			if (lane == null)
			{
				return null;
			}
			Vector2 val = LocalOf(st) + new Vector2(0f, 9f);
			return Vector2.op_Implicit(((KitBoss)m_god).World(val + lane.Dir * 60f));
		}
	}
	internal static class DrownedTemplates
	{
		public static ClipLibrary Body;

		public static ClipLibrary Env;

		public static GameObject BodyTemplate;

		public static GameObject RakeFx;

		public static GameObject HandFx;

		public static GameObject AvoidRake;

		public static GameObject AvoidRipple;

		public static GameObject AvoidRakeLie;

		public static GameObject AvoidRippleLie;

		public static GameObject WhisperFx;

		public static GameObject IdolT;

		public static GameObject SluiceT;

		public static GameObject SeatT;

		public static Vector2 RakeCentreOffset;

		public static Vector2 HandCentreOffset;

		public static Vector2 AvoidRakeCentre;

		public static Vector2 AvoidRippleCentre;

		public static GameObject Build(BossContext ctx)
		{
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: 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_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0216: Unknown result type (might be due to invalid IL or missing references)
			//IL_021d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			//IL_0233: Unknown result type (might be due to invalid IL or missing references)
			//IL_0243: Unknown result type (might be due to invalid IL or missing references)
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: 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_0267: Unknown result type (might be due to invalid IL or missing references)
			//IL_0277: Unknown result type (might be due to invalid IL or missing references)
			//IL_027c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0281: Unknown result type (might be due to invalid IL or missing references)
			//IL_028c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0291: Unknown result type (might be due to invalid IL or missing references)
			//IL_0296: Unknown result type (might be due to invalid IL or missing references)
			//IL_0298: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a2: Expected O, but got Unknown
			//IL_0377: Unknown result type (might be due to invalid IL or missing references)
			//IL_037c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0398: Unknown result type (might be due to invalid IL or missing references)
			//IL_039d: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_04de: Expected O, but got Unknown
			//IL_04eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f5: Expected O, but got Unknown
			//IL_0701: Unknown result type (might be due to invalid IL or missing references)
			KitLog log = ctx.Log;
			CueSet cues = KitSounds.Build(ctx, (IList<CueSpec>)Sounds.Cues, ctx.Holder);
			DrownedCues.Map(cues, log);
			Body = ClipLibrary.Load(ctx, "Drowned", KitArt.MaterialOf("EnemyDarkGuardian"), (Func<string, AudioCue>)((string n) => cues.Get(n)));
			string[] heldClips = Names.HeldClips;
			foreach (string text in heldClips)
			{
				Body.Rebuild(text, (float?)null, (WrapMode?)(WrapMode)8, (IEnumerable<EventInfo>)null, (int[])null);
			}
			Body.Rebuild("DrownedRakeSweep", (float?)null, (WrapMode?)(WrapMode)8, (IEnumerable<EventInfo>)(object)new EventInfo[0], (int[])null);
			Env = ClipLibrary.Load(ctx, "DrownedEnv", KitArt.MaterialOf("TrapProjectileSingle"), (Func<string, AudioCue>)((string n) => cues.Get(n)));
			Env.Rebuild("DrownedWhisper", (float?)null, (WrapMode?)null, (IEnumerable<EventInfo>)(object)new EventInfo[1] { KitArt.Event(0.1f, "AnimDamageOn") }, (int[])null);
			BuildEffects(ctx);
			BodyTemplate = KitBodies.CloneBody(ctx, "EnemyDarkGuardian", "DrownedGodBody", new BodySpec
			{
				Clips = Body,
				Idle = "DrownedIdleVeiled",
				Run = "DrownedRun",
				Dead = "DrownedDeath",
				Statue = "DrownedStatue",
				HealthMax = 48f,
				Resistance = 3f,
				VulnerableMult = 4.5f,
				MaxDamagePerHit = 4f,
				AllowedDamage = (eAllowedDamageSource)2,
				Speed = 30f,
				Mass = 600f,
				KnockbackSpeed = 0f,
				DieSound = DrownedCues.Death,
				AttackSpawnNode = Vector2.zero,
				Attacks = new List<AttackData> { KitFx.Attack(Body["DrownedRakeSweep"], 99f, 0f, 0f) },
				Effects = new List<DamageEffectData>(),
				CapsuleDirection = 0,
				CapsuleRadius = 4f,
				CapsuleHeight = 8f,
				CapsuleCenter = new Vector3(0f, -6f, 0f),
				HitZoneScale = new Vector3(40f, 20f, 64f),
				HitZonePos = new Vector3(0f, -8f, -8f),
				SpriteOffset = new Vector2(0f, -44f),
				Anchor = (Anchor)7
			});
			Player component = BodyTemplate.GetComponent<Player>();
			Util.Set((object)component, "m_shadowPrefab", (object)null);
			try
			{
				Util.Set((object)component, "m_bloodEffectsEnabled", (object)false);
			}
			catch (Exception ex)
			{
				log.Warn("could not switch off the death blood: " + ex.Message);
			}
			Util.Set((object)component, "m_spawnOnHit", (object)new DamageEffectData[0]);
			PropFodder[] components = BodyTemplate.GetComponents<PropFodder>();
			for (int num = 0; num < components.Length; num++)
			{
				Object.DestroyImmediate((Object)(object)components[num]);
			}
			Transform val = BodyTemplate.transform.Find("HitZone");
			BoxCollider val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<BoxCollider>() : null);
			if ((Object)(object)val2 == (Object)null)
			{
				throw new InvalidOperationException("the god's body has no HitZone BoxCollider");
			}
			log.Info("HitZone box after CloneBody: size " + ((object)val2.size/*cast due to .constrained prefix*/).ToString() + " centre " + ((object)val2.center/*cast due to .constrained prefix*/).ToString() + "; held at a unit box");
			val2.size = new Vector3((val2.size.x < 0f) ? (-1f) : 1f, 1f, 1f);
			val2.center = Vector3.zero;
			if ((Object)(object)((Component)val).GetComponent<HitZone>() != (Object)null)
			{
				log.Info("The body's HitZone carries a HitZone component; GodBody writes its offset");
			}
			IdolT = StationTemplates.CloneTrap(ctx, "TrapProjectileSingle", "DrownedIdolStation");
			StationTemplates.Reskin(IdolT, KitArt.TrapStateClips(Env, "DrownedIdol"), 6);
			StationTemplates.SetCooldown(IdolT, 1.4f);
			StationTemplates.SetAim(IdolT, 0f, true, (float[])null, (Vector2?)null, (float?)7.5f);
			List<DamageEffectData> list = Util.Get<List<DamageEffectData>>((object)IdolT.GetComponent<PropTrap>(), "m_attackDamageEffects");
			if (list == null || list.Count == 0 || list[0] == null)
			{
				throw new InvalidOperationException("TrapProjectileSingle has no attack effect to turn into the whisper");
			}
			list[0].m_object = WhisperFx;
			list[0].m_offsetX = new MinMaxRange(0f);
			list[0].m_offsetY = new MinMaxRange(-22f);
			list[0].m_rotateOffsetX = true;
			SluiceT = StationTemplates.CloneTrap(ctx, "TrapBackWallSpout", "DrownedSluiceStation");
			StationTemplates.Reskin(SluiceT, KitArt.TrapStateClips(Env, "DrownedSluice"), 6);
			StationTemplates.StripAttacks(SluiceT, 9f);
			StationTemplates.SetAim(SluiceT, 270f, true, new float[2] { 270f, 330f }, (Vector2?)null, (float?)null);
			SeatT = StationTemplates.CloneTrap(ctx, "TrapProjectileSingle", "DrownedSeatStation");
			StationTemplates.Reskin(SeatT, KitArt.TrapStateClips(Env, "DrownedSeat"), 6);
			StationTemplates.StripAttacks(SeatT, 0.35f);
			StationTemplates.SetIndicator(SeatT, false);
			StationTemplates.SetAim(SeatT, 0f, false, (float[])null, (Vector2?)null, (float?)null);
			Room val3 = KitArena.CloneColosseum(ctx, "DrownedArena");
			Transform val4 = ((Component)val3).transform.Find("BackWallArt");
			if ((Object)(object)val4 != (Object)null)
			{
				((Component)val4).gameObject.SetActive(false);
			}
			else
			{
				log.Warn("The Colosseum has no BackWallArt child; the drowned back wall is drawn over the vanilla one");
			}
			log.Info("Built: body " + ((Texture)Body.Sheet.Atlas.texture).width + "x" + ((Texture)Body.Sheet.Atlas.texture).height + ", env " + ((Texture)Env.Sheet.Atlas.texture).width + "x" + ((Texture)Env.Sheet.Atlas.texture).height);
			return ((Component)KitTemplates.CreateBossTemplate<DrownedGod>(ctx, val3, new Vector2(0f, 44f))).gameObject;
		}

		private unsafe static void BuildEffects(BossContext ctx)
		{
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: 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_0108: 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_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_0218: 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_021c: 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_0229: Unknown result type (might be due to invalid IL or missing references)
			//IL_023d: Unknown result type (might be due to invalid IL or missing references)
			//IL_023f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0274: 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)
			//IL_029e: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0448: Unknown result type (might be due to invalid IL or missing references)
			KitLog log = ctx.Log;
			RakeFx = KitFx.CloneDamage(ctx, "GuardianSwipe1", "DrownedRakeFx", true);
			KitFx.TuneDamage(RakeFx, 2f, 0f, 1.2f, 0f);
			KitFx.SetNullifyable(RakeFx, false);
			ZeroSpawnOffset(RakeFx, required: false, log);
			Effect component = RakeFx.GetComponent<Effect>();
			if ((Object)(object)component != (Object)null)
			{
				Util.Set((object)component, "m_canFlip", (object)false);
			}
			HideSprites(RakeFx);
			RakeFx.transform.localScale = Vector3.one;
			BoxForCapsule(RakeFx, new Vector2(32f, 130f), Vector2.zero, log);
			Vector2 centre;
			Vector2 val = ColliderSize(RakeFx, out centre, log);
			RakeCentreOffset = new Vector2(centre.y, 0f - centre.x);
			string[] obj = new string[9] { "Rake collider: box ", null, null, null, null, null, null, null, null };
			Vector2 val2 = val;
			obj[1] = ((object)(*(Vector2*)(&val2))/*cast due to .constrained prefix*/).ToString();
			obj[2] = " centre ";
			val2 = centre;
			obj[3] = ((object)(*(Vector2*)(&val2))/*cast due to .constrained prefix*/).ToString();
			obj[4] = " (world ";
			obj[5] = 130f.ToString();
			obj[6] = " x ";
			obj[7] = 32f.ToString();
			obj[8] = " at 270)";
			log.Info(string.Concat(obj));
			HandFx = KitFx.CloneDamage(ctx, "DFXHandBase", "DrownedHandFx", true);
			ZeroSpawnOffset(HandFx, required: true, log);
			float num = Util.Get<float>((object)HandFx.GetComponent<DamageEffect>(), "m_damageRate");
			KitFx.TuneDamage(HandFx, 1.5f, num, 1f, 0f);
			HandFx.transform.localScale = Vector3.one;
			CapsuleCollider component2 = HandFx.GetComponent<CapsuleCollider>();
			Vector2 centre2 = (((Object)(object)component2 != (Object)null) ? Vector2.op_Implicit(component2.center) : Vector2.zero);
			BoxForCapsule(HandFx, new Vector2(28f, 14f), centre2, log);
			Vector2 centre3;
			Vector2 val3 = ColliderSize(HandFx, out centre3, log);
			HandCentreOffset = centre3;
			val2 = val3;
			string? text = ((object)(*(Vector2*)(&val2))/*cast due to .constrained prefix*/).ToString();
			val2 = centre3;
			log.Info("Hand collider: box " + text + " centre " + ((object)(*(Vector2*)(&val2))/*cast due to .constrained prefix*/).ToString());
			Vector2 footprint = default(Vector2);
			((Vector2)(ref footprint))..ctor(140f, 50f);
			AvoidRake = MakeAvoid(ctx, "DrownedAvoidRake", 1f, footprint, out AvoidRakeCentre);
			AvoidRakeLie = MakeAvoid(ctx, "DrownedAvoidRakeLie", 0.7f, footprint, out var centreOffset);
			Vector2 footprint2 = val3;
			AvoidRipple = MakeAvoid(ctx, "DrownedAvoidRipple", 1.75f, footprint2, out AvoidRippleCentre);
			AvoidRippleLie = MakeAvoid(ctx, "DrownedAvoidRippleLie", 0.9f, footprint2, out centreOffset);
			WhisperFx = KitFx.CloneDamage(ctx, "DFXTrapProjectile1", "DrownedWhisperFx", true);
			ZeroSpawnOffset(WhisperFx, required: false, log);
			KitFx.TuneDamage(WhisperFx, 0.5f, 0f, 0.15f, 0f);
			exSpriteAnimation component3 = WhisperFx.GetComponent<exSpriteAnimation>();
			exSprite component4 = WhisperFx.GetComponent<exSprite>();
			if ((Object)(object)component3 == (Object)null || (Object)(object)component4 == (Object)null)
			{
				throw new InvalidOperationException("DFXTrapProjectile1 has no sprite animation on its root");
			}
			HashSet<exSpriteAnimClip> hashSet = new HashSet<exSpriteAnimClip>();
			if ((Object)(object)component3.defaultAnimation != (Object)null)
			{
				hashSet.Add(component3.defaultAnimation);
			}
			if (component3.animations != null)
			{
				foreach (exSpriteAnimClip animation in component3.animations)
				{
					if ((Object)(object)animation != (Object)null)
					{
						hashSet.Add(animation);
					}
				}
			}
			exSpriteAnimClip to = Env["DrownedWhisper"];
			int num2 = 0;
			Component[] array = (Component[])(object)new Component[2]
			{
				(Component)component3,
				(Component)WhisperFx.GetComponent<Effect>()
			};
			foreach (Component val4 in array)
			{
				if (!((Object)(object)val4 == (Object)null))
				{
					num2 += SwapOn(val4, hashSet, to);
				}
			}
			if (num2 == 0)
			{
				throw new InvalidOperationException("the whisper clip could not be swapped in");
			}
			((exPlane)component4).anchor = (Anchor)4;
			((exPlane)component4).offset = new Vector2(0f, 18f);
			component4.SetSprite(Env.Sheet.Atlas, Env.Sheet.Frames("DrownedWhisper")[0], true);
			ParticleMotion component5 = WhisperFx.GetComponent<ParticleMotion>();
			if ((Object)(object)component5 != (Object)null)
			{
				Util.Set((object)component5, "m_trailObject", (object)null);
			}
			WhisperFx.AddComponent<WhisperMark>();
			log.Info("Whisper: " + num2 + " clip slots swapped");
		}

		private static int SwapOn(Component comp, HashSet<exSpriteAnimClip> from, exSpriteAnimClip to)
		{
			int num = 0;
			exSpriteAnimation val = (exSpriteAnimation)(object)((comp is exSpriteAnimation) ? comp : null);
			if ((Object)(object)val != (Object)null)
			{
				if ((Object)(object)val.defaultAnimation != (Object)null && from.Contains(val.defaultAnimation))
				{
					val.defaultAnimation = to;
					num++;
				}
				if (val.animations != null)
				{
					for (int i = 0; i < val.animations.Count; i++)
					{
						if ((Object)(object)val.animations[i] != (Object)null && from.Contains(val.animations[i]))
						{
							val.animations[i] = to;
							num++;
						}
					}
				}
				return num;
			}
			Effect val2 = (Effect)(object)((comp is Effect) ? comp : null);
			if ((Object)(object)val2 != (Object)null)
			{
				exSpriteAnimClip val3 = Util.Get<exSpriteAnimClip>((object)val2, "m_animationDefault");
				if ((Object)(object)val3 != (Object)null && from.Contains(val3))
				{
					Util.Set((object)val2, "m_animationDefault", (object)to);
					num++;
				}
			}
			return num;
		}

		private unsafe static GameObject MakeAvoid(BossContext ctx, string name, float life, Vector2 footprint, out Vector2 centreOffset)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: 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_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_006e: 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_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: 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)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = KitFx.CloneDamage(ctx, "DFXBotAvoid-Minotaur", name, true);
			ZeroSpawnOffset(val, required: false, ctx.Log);
			KitFx.SetLifetime(val, life, false);
			Util.Set((object)val.GetComponent<DamageEffect>(), "m_spawnOnHit", (object)null);
			Vector2 centre;
			Vector2 val2 = ColliderSize(val, out centre, ctx.Log);
			float num = footprint.x / val2.x;
			float num2 = footprint.y / val2.y;
			val.transform.localScale = new Vector3(num, num2, 1f);
			centreOffset = new Vector2(num * centre.x, num2 * centre.y);
			KitLog log = ctx.Log;
			string[] obj = new string[10] { name, " collider ", null, null, null, null, null, null, null, null };
			Vector2 val3 = val2;
			obj[2] = ((object)(*(Vector2*)(&val3))/*cast due to .constrained prefix*/).ToString();
			obj[3] = " centre ";
			val3 = centre;
			obj[4] = ((object)(*(Vector2*)(&val3))/*cast due to .constrained prefix*/).ToString();
			obj[5] = " -> scale (";
			obj[6] = num.ToString();
			obj[7] = ", ";
			obj[8] = num2.ToString();
			obj[9] = ")";
			log.Info(string.Concat(obj));
			return val;
		}

		private static void ZeroSpawnOffset(GameObject go, bool required, KitLog log)
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Expected O, but got Unknown
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Expected O, but got Unknown
			Effect component = go.GetComponent<Effect>();
			if ((Object)(object)component == (Object)null)
			{
				if (required)
				{
					throw new InvalidOperationException(((Object)go).name + " has no Effect on its root");
				}
				log.Info(((Object)go).name + " has no Effect on its root; nothing offsets its spawn");
				return;
			}
			MinMaxRange val = Util.Get<MinMaxRange>((object)component, "m_offsetX");
			MinMaxRange val2 = Util.Get<MinMaxRange>((object)component, "m_offsetY");
			Util.Set((object)component, "m_offsetX", (object)new MinMaxRange(0f));
			Util.Set((object)component, "m_offsetY", (object)new MinMaxRange(0f));
			if ((val != null && (val.Min != 0f || val.Max != 0f)) || (val2 != null && (val2.Min != 0f || val2.Max != 0f)))
			{
				log.Info(((Object)go).name + " spawn offset (" + ((val != null) ? (val.Min + ".." + val.Max) : "null") + ", " + ((val2 != null) ? (val2.Min + ".." + val2.Max) : "null") + ") set to 0");
			}
		}

		private static void BoxForCapsule(GameObject go, Vector2 size, Vector2 centre, KitLog log)
		{
			//IL_0042: 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_0080: 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_008e: Unknown result type (might be due to invalid IL or missing references)
			CapsuleCollider component = go.GetComponent<CapsuleCollider>();
			if ((Object)(object)component == (Object)null)
			{
				throw new InvalidOperationException(((Object)go).name + " has no CapsuleCollider on its root to replace");
			}
			bool isTrigger = ((Collider)component).isTrigger;
			PhysicMaterial sharedMaterial = ((Collider)component).sharedMaterial;
			float num = 2f * component.radius;
			float z = component.center.z;
			Object.DestroyImmediate((Object)(object)component);
			BoxCollider obj = go.AddComponent<BoxCollider>();
			((Collider)obj).isTrigger = isTrigger;
			((Collider)obj).sharedMaterial = sharedMaterial;
			obj.size = new Vector3(size.x, size.y, num);
			obj.center = new Vector3(centre.x, centre.y, z);
			int num2 = go.GetComponentsInChildren<Collider>(true).Length - 1;
			if (num2 != 0)
			{
				log.Warn(((Object)go).name + ": " + num2 + " more collider(s) besides the new box");
			}
		}

		private unsafe static Vector2 ColliderSize(GameObject go, out Vector2 centre, KitLog log)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Expected O, but got Unknown
			//IL_0049: 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_006e: 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_0078: 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_008e: Expected O, but got Unknown
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: 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_00d1: Expected O, but got Unknown
			//IL_0220: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: 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_01fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: 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_0204: 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_0210: 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_021f: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0245: Unknown result type (might be due to invalid IL or missing references)
			//IL_0246: 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_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: 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_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)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0266: Unknown result type (might be due to invalid IL or missing references)
			//IL_0267: Unknown result type (might be due to invalid IL or missing references)
			//IL_026c: Unknown result type (might be due to invalid IL or missing references)
			Collider val = go.GetComponent<Collider>();
			if ((Object)(object)val == (Object)null)
			{
				val = go.GetComponentInChildren<Collider>(true);
			}
			if ((Object)(object)val == (Object)null)
			{
				throw new InvalidOperationException(((Object)go).name + " has no collider");
			}
			Vector2 val3 = default(Vector2);
			Vector2 val4;
			if (val is BoxCollider)
			{
				BoxCollider val2 = (BoxCollider)val;
				((Vector2)(ref val3))..ctor(Mathf.Abs(val2.size.x), Mathf.Abs(val2.size.y));
				val4 = Vector2.op_Implicit(val2.center);
			}
			else if (val is SphereCollider)
			{
				SphereCollider val5 = (SphereCollider)val;
				((Vector2)(ref val3))..ctor(2f * val5.radius, 2f * val5.radius);
				val4 = Vector2.op_Implicit(val5.center);
			}
			else if (val is CapsuleCollider)
			{
				CapsuleCollider val6 = (CapsuleCollider)val;
				float num = Mathf.Max(val6.height, 2f * val6.radius);
				val3 = ((val6.direction == 0) ? new Vector2(num, 2f * val6.radius) : new Vector2(2f * val6.radius, num));
				val4 = Vector2.op_Implicit(val6.center);
			}
			else
			{
				if (!(val is MeshCollider) || !((Object)(object)((MeshCollider)val).sharedMesh != (Object)null))
				{
					throw new InvalidOperationException(((Object)go).name + ": collider " + ((object)val).GetType().Name + " cannot be measured");
				}
				Bounds bounds = ((MeshCollider)val).sharedMesh.bounds;
				((Vector2)(ref val3))..ctor(((Bounds)(ref bounds)).size.x, ((Bounds)(ref bounds)).size.y);
				val4 = Vector2.op_Implicit(((Bounds)(ref bounds)).center);
			}
			if ((Object)(object)((Component)val).transform != (Object)(object)go.transform)
			{
				Transform transform = ((Component)val).transform;
				val3 = Vector2.Scale(val3, new Vector2(Mathf.Abs(transform.localScale.x), Mathf.Abs(transform.localScale.y)));
				val4 = Vector2.Scale(val4, Vector2.op_Implicit(transform.localScale)) + Vector2.op_Implicit(transform.localPosition);
			}
			if (val3.x < 0.01f || val3.y < 0.01f)
			{
				string name = ((Object)go).name;
				Vector2 val7 = val3;
				throw new InvalidOperationException(name + ": collider footprint " + ((object)(*(Vector2*)(&val7))/*cast due to .constrained prefix*/).ToString() + " is empty");
			}
			centre = val4;
			return val3;
		}

		private static void HideSprites(GameObject go)
		{
			exSprite[] componentsInChildren = go.GetComponentsInChildren<exSprite>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				((Behaviour)componentsInChildren[i]).enabled = false;
			}
			Renderer[] componentsInChildren2 = go.GetComponentsInChildren<Renderer>(true);
			for (int i = 0; i < componentsInChildren2.Length; i++)
			{
				componentsInChildren2[i].enabled = false;
			}
		}
	}
	internal sealed class Gaze
	{
		private sealed class Disc
		{
			public Vector2 A;

			public Vector2 P;

			public Vector2 B;

			public float Launch;

			public float T1;

			public float T2;

			public exSprite Spr;

			public bool Finding;

			public Vector2 Pos;

			public readonly List<exSprite> Tel = new List<exSprite>();
		}

		private readonly DrownedGod m_god;

		private readonly List<Disc> m_discs = new List<Disc>();

		private ClipLibrary Env => DrownedTemplates.Env;

		public bool Any => m_discs.Count > 0;

		public Gaze(DrownedGod god)
		{
			m_god = god;
		}

		public void Telegraph(Vector2 p, bool second, float launchAt)
		{
			//IL_0007: 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)
			FadeAll();
			Disc disc = Plan(p, vertical: false);
			Disc disc2 = (second ? Plan(p, vertical: true) : null);
			float num = 0f;
			float num2 = 0f;
			if (disc2 != null)
			{
				num2 = disc.T1 + 0.5f - disc2.T1;
				if (num2 < 0f)
				{
					num = 0f - num2;
					num2 = 0f;
				}
			}
			disc.Launch = launchAt + num;
			m_discs.Add(disc);
			Outline(disc);
			if (disc2 != null)
			{
				disc2.Launch = launchAt + num2;
				m_discs.Add(disc2);
				Outline(disc2);
			}
		}

		private Disc Plan(Vector2 p, bool vertical)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: 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_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_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: 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_0044: 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_005d: 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_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: 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_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: 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)
			//IL_008b: 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)
			Disc disc = new Disc
			{
				P = p
			};
			if (!vertical)
			{
				float num = Edge(p, new Vector2(-1f, 0f));
				float num2 = Edge(p, new Vector2(1f, 0f));
				Vector2 val = default(Vector2);
				((Vector2)(ref val))..ctor(num, p.y);
				Vector2 val2 = default(Vector2);
				((Vector2)(ref val2))..ctor(num2, p.y);
				bool flag = p.x - num >= num2 - p.x;
				disc.A = (flag ? val : val2);
				disc.B = (flag ? val2 : val);
			}
			else
			{
				float num3 = Edge(p, new Vector2(0f, 1f));
				float num4 = Edge(p, new Vector2(0f, -1f));
				disc.A = new Vector2(p.x, num3);
				disc.B = new Vector2(p.x, num4);
			}
			disc.T1 = Vector2.Distance(disc.A, disc.P) / 100f;
			disc.T2 = Vector2.Distance(disc.P, disc.B) / 100f;
			disc.Pos = disc.A;
			return disc;
		}

		private float Edge(Vector2 p, Vector2 dir)
		{
			//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_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: 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)
			//IL_0065: 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_0067: 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_0034: 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)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_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_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to inval

plugins/CrawlCustomBosses/KrakenBoss.dll

Decompiled 4 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BossKit;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("KrakenBoss")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("KrakenBoss")]
[assembly: AssemblyTitle("KrakenBoss")]
[assembly: AssemblyVersion("1.0.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 KrakenBoss
{
	internal enum ArmPhase
	{
		Free,
		Rise,
		Wrap,
		Hold,
		Taut,
		Whip
	}
	internal sealed class ArmState
	{
		public int Id;

		public ArmPhase Phase;

		public int Cleat = -1;

		public float Timer;
	}
	internal sealed class KrakenHold
	{
		public const float RiseTime = 0.4f;

		public const float ClampTime = 0.4f;

		public const float WhipTime = 0.4f;

		public readonly ArmState[] Arms = new ArmState[3]
		{
			new ArmState
			{
				Id = 0
			},
			new ArmState
			{
				Id = 1
			},
			new ArmState
			{
				Id = 2
			}
		};

		public readonly CleatState[] Cleats;

		public readonly DeckList Deck;

		public bool Enabled;

		public int HeroSide = 1;

		public float HeroY;

		public float HeroX;

		public int HeaveArm = -1;

		public bool HeaveActive;

		public bool HeadAway;

		public bool Riding;

		public Func<float, float, float> Range = Random.Range;

		private float m_planTimer;

		private float m_underFor;

		private float m_heaveTimer = 9f;

		private float m_heaveLeft;

		public event Action<ArmState> Changed;

		public event Action<ArmState> HeaveStarted;

		public KrakenHold(CleatState[] cleats, DeckList deck)
		{
			Cleats = cleats;
			Deck = deck;
		}

		public float ActiveSum()
		{
			float num = 0f;
			CleatState[] cleats = Cleats;
			foreach (CleatState cleatState in cleats)
			{
				if (cleatState.Held && cleatState.Awake)
				{
					num += (float)cleatState.Side * 0.25f;
				}
			}
			if (HeaveActive && HeaveArm >= 0 && Arms[HeaveArm].Cleat >= 0)
			{
				num += (float)Cleats[Arms[HeaveArm].Cleat].Side * 0.3f;
			}
			return num;
		}

		public float WorstSum(float immediate, float pending)
		{
			float num2;
			float num = (num2 = ActiveSum() + immediate);
			ArmState[] arms = Arms;
			foreach (ArmState armState in arms)
			{
				if ((armState.Phase == ArmPhase.Rise || armState.Phase == ArmPhase.Wrap) && armState.Cleat >= 0 && !Cleats[armState.Cleat].Held)
				{
					float num3 = (float)Cleats[armState.Cleat].Side * 0.25f;
					if (num3 > 0f)
					{
						num2 += num3;
					}
					else
					{
						num += num3;
					}
				}
			}
			if (!HeaveActive && HeaveArm >= 0 && Arms[HeaveArm].Phase == ArmPhase.Taut && Arms[HeaveArm].Cleat >= 0)
			{
				float num4 = (float)Cleats[Arms[HeaveArm].Cleat].Side * 0.3f;
				if (num4 > 0f)
				{
					num2 += num4;
				}
				else
				{
					num += num4;
				}
			}
			if (pending > 0f)
			{
				num2 += pending;
			}
			else
			{
				num += pending;
			}
			return Mathf.Max(Mathf.Abs(num2), Mathf.Abs(num));
		}

		public bool Allowed(float immediate, float pending)
		{
			if (!Deck.AnyUnder)
			{
				return WorstSum(immediate, pending) + 0.2f < 0.8f;
			}
			return false;
		}

		public int HeldCoils(int side)
		{
			int num = 0;
			for (int i = 0; i < Cleats.Length; i++)
			{
				if (Cleats[i].Side == side && Cleats[i].Held && Cleats[i].Awake)
				{
					num++;
				}
			}
			return num;
		}

		public int PendingCoils(int side)
		{
			int num = 0;
			ArmState[] arms = Arms;
			foreach (ArmState armState in arms)
			{
				if ((armState.Phase == ArmPhase.Rise || armState.Phase == ArmPhase.Wrap) && armState.Cleat >= 0 && !Cleats[armState.Cleat].Held && Cleats[armState.Cleat].Side == side)
				{
					num++;
				}
			}
			return num;
		}

		public bool AfterPullFits(int side, int add, int leaving)
		{
			int num = HeldCoils(side) + PendingCoils(side) + add - leaving;
			int num2 = HeldCoils(-side);
			return (float)(num - Mathf.Max(num2 - 1, 0)) * 0.25f - 0.2f < 0.5f;
		}

		public bool RoomOnRail(int side, int leaving)
		{
			return AfterPullFits(side, 1, leaving);
		}

		public bool PullFrees(int cleat)
		{
			int side = Cleats[cleat].Side;
			int num = HeldCoils(-side) + PendingCoils(-side);
			int num2 = HeldCoils(side) - 1;
			return (float)(num - num2) * 0.25f - 0.2f < 0.5f;
		}

		private void Set(ArmState a, ArmPhase p, int cleat)
		{
			a.Phase = p;
			a.Cleat = cleat;
			a.Timer = 0f;
			this.Changed?.Invoke(a);
		}

		public bool IsTargeted(int cleat)
		{
			ArmState[] arms = Arms;
			foreach (ArmState armState in arms)
			{
				if (armState.Cleat == cleat && armState.Phase != ArmPhase.Free && armState.Phase != ArmPhase.Whip)
				{
					return true;
				}
			}
			return false;
		}

		public bool TryWrap(ArmState a, int cleat)
		{
			if (a.Phase != ArmPhase.Free || cleat < 0 || !Cleats[cleat].Awake || Cleats[cleat].Held || IsTargeted(cleat))
			{
				return false;
			}
			if (!Allowed(0f, (float)Cleats[cleat].Side * 0.25f) || !RoomOnRail(Cleats[cleat].Side, 0))
			{
				return false;
			}
			Set(a, ArmPhase.Rise, cleat);
			return true;
		}

		private void Release(ArmState a)
		{
			int cleat = a.Cleat;
			if (cleat >= 0 && Cleats[cleat].Holder == Holder.Arm && Cleats[cleat].HolderId == a.Id)
			{
				Cleats[cleat].Holder = Holder.None;
				Cleats[cleat].Blows = 0;
			}
			if (HeaveArm == a.Id)
			{
				HeaveArm = -1;
				HeaveActive = false;
			}
			Set(a, ArmPhase.Whip, cleat);
		}

		public void LetGo(int cleat)
		{
			ArmState[] arms = Arms;
			foreach (ArmState armState in arms)
			{
				if (armState.Cleat == cleat && armState.Phase != ArmPhase.Free && armState.Phase != ArmPhase.Whip)
				{
					Release(armState);
				}
			}
		}

		public void LetGoAll()
		{
			ArmState[] arms = Arms;
			foreach (ArmState armState in arms)
			{
				if (armState.Phase != ArmPhase.Free && armState.Phase != ArmPhase.Whip)
				{
					Release(armState);
				}
			}
		}

		public void ResetTimers()
		{
			m_planTimer = 2f;
			m_heaveTimer = Range(9f, 11f);
		}

		public void Step(float dt)
		{
			ArmState[] arms = Arms;
			foreach (ArmState a in arms)
			{
				StepArm(a, dt);
			}
			if (HeaveActive)
			{
				m_heaveLeft -= dt;
				if (m_heaveLeft <= 0f)
				{
					HeaveActive = false;
					ArmState armState = ((HeaveArm >= 0) ? Arms[HeaveArm] : null);
					HeaveArm = -1;
					if (armState != null && armState.Phase == ArmPhase.Taut)
					{
						Set(armState, ArmPhase.Hold, armState.Cleat);
					}
				}
			}
			m_underFor = (Deck.AnyUnder ? (m_underFor + dt) : 0f);
			if (Enabled)
			{
				m_planTimer -= dt;
				if (m_planTimer <= 0f)
				{
					m_planTimer = 2f;
					Plan();
				}
				m_heaveTimer -= dt;
				if (m_heaveTimer <= 0f)
				{
					m_heaveTimer = (TryHeave() ? Range(9f, 11f) : 1f);
				}
			}
		}

		private void StepArm(ArmState a, float dt)
		{
			a.Timer += dt;
			switch (a.Phase)
			{
			case ArmPhase.Rise:
				if (a.Timer >= 0.4f)
				{
					Set(a, ArmPhase.Wrap, a.Cleat);
				}
				break;
			case ArmPhase.Wrap:
				if (a.Timer >= 0.4f)
				{
					CleatState cleatState = Cleats[a.Cleat];
					if (cleatState.Awake && !cleatState.Held && Allowed(0f, 0f) && AfterPullFits(cleatState.Side, 0, 0))
					{
						cleatState.Holder = Holder.Arm;
						cleatState.HolderId = a.Id;
						cleatState.Blows = 0;
						Set(a, ArmPhase.Hold, a.Cleat);
					}
					else
					{
						Set(a, ArmPhase.Whip, a.Cleat);
					}
				}
				break;
			case ArmPhase.Taut:
				if (!HeaveActive && HeaveArm == a.Id && a.Timer >= 0.4f)
				{
					HeaveActive = true;
					m_heaveLeft = 3f;
					this.HeaveStarted?.Invoke(a);
				}
				break;
			case ArmPhase.Whip:
				if (a.Timer >= 0.4f)
				{
					Set(a, ArmPhase.Free, -1);
					m_planTimer = Mathf.Min(m_planTimer, 0.1f);
				}
				break;
			case ArmPhase.Hold:
				break;
			}
		}

		public List<int> Wanted()
		{
			List<int> list = new List<int>();
			int num = -HeroSide;
			List<int> list2 = new List<int>();
			List<int> list3 = new List<int>();
			for (int i = 0; i < Cleats.Length; i++)
			{
				CleatState cleatState = Cleats[i];
				if (cleatState.Side == num && cleatState.Awake)
				{
					if (cleatState.Holder == Holder.Arm)
					{
						list2.Add(i);
					}
					else if (cleatState.Holder == Holder.None)
					{
						list3.Add(i);
					}
				}
			}
			list3.Sort(delegate(int x, int y)
			{
				int num6 = Mathf.Abs(YOf(y) - HeroY).CompareTo(Mathf.Abs(YOf(x) - HeroY));
				return (num6 == 0) ? x.CompareTo(y) : num6;
			});
			foreach (int item in list2)
			{
				if (list.Count < 2)
				{
					list.Add(item);
				}
			}
			foreach (int item2 in list3)
			{
				if (list.Count < 2)
				{
					list.Add(item2);
				}
			}
			int num2 = -1;
			float num3 = -1f;
			bool flag = false;
			for (int num4 = 0; num4 < Cleats.Length; num4++)
			{
				CleatState cleatState2 = Cleats[num4];
				if (cleatState2.Side == HeroSide && cleatState2.Awake && cleatState2.Holder != Holder.Capstan)
				{
					bool flag2 = cleatState2.Holder == Holder.Arm;
					float num5 = Mathf.Abs(YOf(num4) - HeroY);
					if ((flag2 && !flag) || (flag2 == flag && num5 > num3 + 0.001f))
					{
						num2 = num4;
						num3 = num5;
						flag = flag2;
					}
				}
			}
			if (num2 >= 0)
			{
				list.Add(num2);
			}
			return list;
		}

		private static float YOf(int cleat)
		{
			return Layout.Cleats[cleat].y;
		}

		private void Plan()
		{
			if (Deck.AnyUnder && (HeadAway || (Riding && m_underFor >= Tuning.UpMax[3])))
			{
				Unstick();
			}
			Trim();
			List<int> list = Wanted();
			ArmState[] arms = Arms;
			foreach (ArmState armState in arms)
			{
				if (armState.Phase == ArmPhase.Hold && HeaveArm != armState.Id && !list.Contains(armState.Cleat) && !Engaged(armState.Cleat) && Allowed((float)(-Cleats[armState.Cleat].Side) * 0.25f, 0f))
				{
					Release(armState);
				}
			}
			arms = Arms;
			foreach (ArmState armState2 in arms)
			{
				if (armState2.Phase != ArmPhase.Free)
				{
					continue;
				}
				foreach (int item in list)
				{
					if (TryWrap(armState2, item))
					{
						break;
					}
				}
			}
		}

		private void Trim()
		{
			for (int num = 1; num >= -1; num -= 2)
			{
				if (!AfterPullFits(num, 0, 0))
				{
					ArmState[] arms = Arms;
					foreach (ArmState armState in arms)
					{
						if (armState.Phase == ArmPhase.Hold && HeaveArm != armState.Id && armState.Cleat >= 0 && Cleats[armState.Cleat].Side == num && !Engaged(armState.Cleat) && Allowed((float)(-num) * 0.25f, 0f))
						{
							Release(armState);
							break;
						}
					}
				}
			}
		}

		private void Unstick()
		{
			int num = (Deck.IsUnder(1) ? 1 : (-1));
			float num2 = 0f;
			CleatState[] cleats = Cleats;
			foreach (CleatState cleatState in cleats)
			{
				if (cleatState.Held && cleatState.Awake)
				{
					num2 += (float)(cleatState.Side * num) * 0.25f;
				}
			}
			if (num2 - 0.2f < 0.5f)
			{
				return;
			}
			ArmState[] arms = Arms;
			foreach (ArmState armState in arms)
			{
				if (armState.Phase == ArmPhase.Hold && HeaveArm != armState.Id && armState.Cleat >= 0 && Cleats[armState.Cleat].Side == num && !Engaged(armState.Cleat))
				{
					Release(armState);
					break;
				}
			}
		}

		private bool Engaged(int cleat)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			if (cleat >= 0)
			{
				if (Cleats[cleat].Blows <= 0)
				{
					return Layout.InFoothold(cleat, new Vector2(HeroX, HeroY));
				}
				return true;
			}
			return false;
		}

		private bool TryHeave()
		{
			if (HeaveArm >= 0)
			{
				return false;
			}
			int num = -HeroSide;
			ArmState[] arms = Arms;
			foreach (ArmState armState in arms)
			{
				if (armState.Phase == ArmPhase.Hold && armState.Cleat >= 0 && Cleats[armState.Cleat].Side == num)
				{
					if (!Allowed(0f, (float)num * 0.3f))
					{
						return false;
					}
					HeaveArm = armState.Id;
					Set(armState, ArmPhase.Taut, armState.Cleat);
					return true;
				}
			}
			return false;
		}
	}
	internal sealed class ArmVisual
	{
		private readonly HafgufaBoss m_boss;

		private readonly exSprite m_root;

		private readonly exSprite m_wrap;

		private readonly exSpriteAnimation m_rootAnim;

		private readonly exSpriteAnimation m_wrapAnim;

		private ArmPhase m_phase;

		private bool m_rootOn;

		private bool m_wrapOn;

		private bool m_wrapHoldPending;

		private float m_hideTimer;

		public ArmVisual(HafgufaBoss boss, Room room, string name)
		{
			//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_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			m_boss = boss;
			ClipLibrary body = Templates.Body;
			m_root = KitArt.CreateSprite(((Component)room).transform, body.Sheet, "HafgufaArm_Hold", 0, ((KitBoss)boss).World(Vector2.zero), (Anchor)7, true, 0.3f);
			((Object)((Component)m_root).gameObject).name = name + "Root";
			m_rootAnim = KitArt.Animate(m_root, (IEnumerable<exSpriteAnimClip>)(object)new exSpriteAnimClip[4]
			{
				body["HafgufaArm_Rise"],
				body["HafgufaArm_Hold"],
				body["HafgufaArm_Taut"],
				body["HafgufaArm_WhipOff"]
			}, (exSpriteAnimClip)null, false);
			m_wrap = KitArt.CreateSprite(((Component)room).transform, body.Sheet, "HafgufaWrap_Hold", 0, ((KitBoss)boss).World(Vector2.zero), (Anchor)7, true, -0.2f);
			((Object)((Component)m_wrap).gameObject).name = name + "Wrap";
			((exPlane)m_wrap).offset = Layout.WrapOffset;
			m_wrapAnim = KitArt.Animate(m_wrap, (IEnumerable<exSpriteAnimClip>)(object)new exSpriteAnimClip[4]
			{
				body["HafgufaWrap_Wrap"],
				body["HafgufaWrap_Hold"],
				body["HafgufaWrap_Taut"],
				body["HafgufaWrap_WhipOff"]
			}, (exSpriteAnimClip)null, false);
			Fx.EnsureCueSource(((Component)m_wrap).gameObject);
			Fx.EnsureCueSource(((Component)m_root).gameObject);
			Apply();
		}

		public void PlaceAtCleat(int cleat)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			PlaceRoot(Layout.ArmRoot(cleat), Layout.SideOf(cleat));
			Vector3 val = ((KitBoss)m_boss).World(Layout.Cleats[cleat]);
			((Component)m_wrap).transform.position = new Vector3(val.x, val.y, ((Component)m_wrap).transform.position.z);
			Vector3 localScale = ((Component)m_wrap).transform.localScale;
			((Component)m_wrap).transform.localScale = new Vector3((Layout.SideOf(cleat) > 0) ? (-1f) : 1f, localScale.y, localScale.z);
		}

		public void PlaceRoot(Vector2 local, int side)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//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_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: 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_006f: 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: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = ((KitBoss)m_boss).World(local);
			((Component)m_root).transform.position = new Vector3(val.x, val.y, ((Component)m_root).transform.position.z);
			Vector3 localScale = ((Component)m_root).transform.localScale;
			((Component)m_root).transform.localScale = new Vector3((side > 0) ? (-1f) : 1f, localScale.y, localScale.z);
		}

		public void Show(ArmPhase p)
		{
			m_phase = p;
			m_wrapHoldPending = false;
			switch (p)
			{
			case ArmPhase.Free:
				m_rootOn = (m_wrapOn = false);
				break;
			case ArmPhase.Rise:
				m_rootOn = true;
				m_wrapOn = false;
				m_rootAnim.Play(Clip("HafgufaArm_Rise"));
				break;
			case ArmPhase.Wrap:
				m_rootOn = (m_wrapOn = true);
				m_rootAnim.Play(Clip("HafgufaArm_Hold"));
				m_wrapAnim.Play(Clip("HafgufaWrap_Wrap"));
				m_wrapHoldPending = true;
				break;
			case ArmPhase.Hold:
				m_rootOn = (m_wrapOn = true);
				m_rootAnim.Play(Clip("HafgufaArm_Hold"));
				if (m_wrapAnim.IsPlaying(Clip("HafgufaWrap_Wrap")))
				{
					m_wrapHoldPending = true;
				}
				else
				{
					m_wrapAnim.Play(Clip("HafgufaWrap_Hold"));
				}
				break;
			case ArmPhase.Taut:
				m_rootOn = (m_wrapOn = true);
				m_rootAnim.Play(Clip("HafgufaArm_Taut"));
				m_wrapAnim.Play(Clip("HafgufaWrap_Taut"));
				break;
			case ArmPhase.Whip:
				m_rootOn = true;
				m_rootAnim.Play(Clip("HafgufaArm_WhipOff"));
				if (m_wrapOn)
				{
					m_wrapAnim.Play(Clip("HafgufaWrap_WhipOff"));
				}
				break;
			}
			Apply();
		}

		public void ShowRootRise()
		{
			m_phase = ArmPhase.Rise;
			m_rootOn = true;
			m_wrapOn = false;
			m_rootAnim.Play(Clip("HafgufaArm_Rise"));
			Apply();
		}

		public void HideAfter(float t)
		{
			m_hideTimer = t;
		}

		private static string Clip(string name)
		{
			return ((Object)Templates.Body[name]).name;
		}

		public void Tick(float dt)
		{
			if (m_wrapHoldPending && !m_wrapAnim.IsPlaying(Clip("HafgufaWrap_Wrap")))
			{
				m_wrapHoldPending = false;
				if (m_phase == ArmPhase.Wrap || m_phase == ArmPhase.Hold)
				{
					m_wrapAnim.Play(Clip("HafgufaWrap_Hold"));
				}
			}
			if (m_phase == ArmPhase.Rise && !m_wrapOn && !m_rootAnim.IsPlaying(Clip("HafgufaArm_Rise")) && !m_rootAnim.IsPlaying(Clip("HafgufaArm_Hold")))
			{
				m_rootAnim.Play(Clip("HafgufaArm_Hold"));
			}
			if (m_phase == ArmPhase.Whip && !m_rootAnim.IsPlaying(Clip("HafgufaArm_WhipOff")))
			{
				m_rootOn = (m_wrapOn = false);
			}
			if (m_hideTimer > 0f)
			{
				m_hideTimer -= dt;
				if (m_hideTimer <= 0f)
				{
					m_rootOn = (m_wrapOn = false);
					m_phase = ArmPhase.Free;
				}
			}
			Apply();
		}

		public void Apply()
		{
			Fx.Show(m_root, m_rootOn);
			Fx.Show(m_wrap, m_wrapOn);
		}
	}
	internal sealed class Cleat
	{
		public readonly CleatState State;

		public readonly int Index;

		private readonly HafgufaBoss m_boss;

		private readonly exSprite m_cleat;

		private readonly exSprite m_pin;

		private readonly exSprite m_drip;

		private readonly Hittable m_hit;

		private readonly int[] m_iron;

		private readonly int[] m_green;

		private readonly int[] m_bright;

		private int m_shownFrame = -1;

		private int m_shownKind = -1;

		private bool m_hitOn = true;

		private float m_flyTimer;

		private bool m_wantPin;

		private bool m_wantDrip;

		public bool Green { get; private set; }

		public Vector2 Local => Layout.Cleats[Index];

		public event Action<Cleat> Blow;

		public Cleat(HafgufaBoss boss, Room room, CleatState state, Sheet env)
		{
			//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_0065: 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_006c: 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_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: 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_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: Unknown result type (might be due to invalid IL or missing references)
			m_boss = boss;
			State = state;
			Index = state.Index;
			Vector2 val = Layout.Cleats[Index];
			EnvStrip hafgufaCleat = EnvLayout.HafgufaCleat;
			m_cleat = KitArt.CreateSprite(((Component)room).transform, env, hafgufaCleat.Name, (!state.Awake) ? 1 : 0, ((KitBoss)boss).World(val), hafgufaCleat.Anchor, true, 0f);
			((exPlane)m_cleat).offset = hafgufaCleat.Offset;
			((Object)((Component)m_cleat).gameObject).name = "HafgufaCleat_" + Index;
			m_iron = env.Frames("HafgufaPin");
			m_green = env.Frames("HafgufaPinGreen");
			m_bright = env.Frames("HafgufaPinGreenBright");
			EnvStrip hafgufaPin = EnvLayout.HafgufaPin;
			m_pin = KitArt.CreateSprite(((Component)room).transform, env, hafgufaPin.Name, 0, ((KitBoss)boss).World(val), hafgufaPin.Anchor, true, -0.4f);
			((exPlane)m_pin).offset = hafgufaPin.Offset;
			((Object)((Component)m_pin).gameObject).name = "HafgufaPin_" + Index;
			EnvStrip hafgufaPinDrip = EnvLayout.HafgufaPinDrip;
			m_drip = KitArt.CreateSprite(((Component)room).transform, env, hafgufaPinDrip.Name, 0, ((KitBoss)boss).World(val + Layout.DripOffset(Index)), hafgufaPinDrip.Anchor, true, -0.4f);
			((exPlane)m_drip).offset = hafgufaPinDrip.Offset;
			((Object)((Component)m_drip).gameObject).name = "HafgufaPinDrip_" + Index;
			KitArt.Animate(m_drip, (IEnumerable<exSpriteAnimClip>)null, Templates.Env["HafgufaPinDrip"], true);
			m_hit = Hittable.Create(((Component)room).transform, "HafgufaPinHit_" + Index, ((KitBoss)boss).World(Layout.PinCentre(Index)), Tuning.PinHurtbox, (eAllowedDamageSource)2, (Action<Hittable, DamageInfo>)OnHit, true, 25, 1f);
			m_hit.MinGap = 0.45f;
			Refresh(green: false, covered: false, 0f);
		}

		private void OnHit(Hittable h, DamageInfo info)
		{
			//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)
			if (State.Held && State.Awake && KitHealth.IsHeroHit(info))
			{
				Player val = Util.Hero();
				if (!((Object)(object)val == (Object)null) && (HafgufaBoss.IsBotHero(val) || Layout.InFoothold(Index, ((KitBoss)m_boss).RoomLocal(((Component)val).transform.position))))
				{
					this.Blow?.Invoke(this);
				}
			}
		}

		public void Wake()
		{
			State.Awake = true;
			SetCleatFrame(0);
		}

		private void SetCleatFrame(int f)
		{
			int[] array = Templates.EnvSheet.Frames("HafgufaCleat");
			m_cleat.SetSprite(Templates.EnvSheet.Atlas, array[f], false);
		}

		public void FlyOut()
		{
			m_flyTimer = 0.3f;
			SetPin(0, 3);
		}

		public void Refresh(bool green, bool covered, float time)
		{
			Green = green && State.Held && State.Awake;
			if (m_flyTimer > 0f)
			{
				m_flyTimer -= Time.deltaTime;
				ShowPin(on: true);
				ShowDrip(on: false);
				SetHit(on: false);
				if (m_flyTimer <= 0f)
				{
					ShowPin(on: false);
				}
				return;
			}
			bool flag = State.Held && State.Awake;
			ShowPin(flag);
			SetHit(flag && m_boss.PinsLive && !covered);
			ShowDrip(Green);
			if (flag)
			{
				int kind = (Green ? (((Mathf.FloorToInt(time * 6f) & 1) == 0) ? 1 : 2) : 0);
				SetPin(kind, Mathf.Clamp(State.Blows, 0, 2));
			}
		}

		private void SetPin(int kind, int frame)
		{
			if (kind != m_shownKind || frame != m_shownFrame)
			{
				m_shownKind = kind;
				m_shownFrame = frame;
				int[] array = kind switch
				{
					1 => m_green, 
					0 => m_iron, 
					_ => m_bright, 
				};
				m_pin.SetSprite(Templates.EnvSheet.Atlas, array[frame], false);
			}
		}

		private void ShowPin(bool on)
		{
			m_wantPin = on;
			Fx.Show(m_pin, on);
		}

		private void ShowDrip(bool on)
		{
			m_wantDrip = on;
			Fx.Show(m_drip, on);
		}

		public void Apply()
		{
			Fx.Show(m_pin, m_wantPin);
			Fx.Show(m_drip, m_wantDrip);
		}

		private void SetHit(bool on)
		{
			if (m_hitOn != on && (Object)(object)m_hit != (Object)null)
			{
				m_hitOn = on;
				m_hit.SetActive(on);
			}
		}
	}
	internal enum Holder
	{
		None,
		Arm,
		Capstan
	}
	internal sealed class CleatState
	{
		public int Index;

		public int Side;

		public bool Awake;

		public Holder Holder;

		public int HolderId;

		public int Blows;

		public float LastBlow;

		public bool Held => Holder != Holder.None;
	}
	internal enum Band
	{
		Level,
		Light,
		Hard,
		Under
	}
	internal sealed class DeckList
	{
		public float L;

		public float T;

		public float DLdt;

		public int Phase = 1;

		public bool Calm;

		public float SwellAngle;

		private float m_jumpLeft;

		private readonly bool[] m_under = new bool[2];

		private readonly Band[] m_band = new Band[2];

		public bool AnyUnder
		{
			get
			{
				if (!m_under[0])
				{
					return m_under[1];
				}
				return true;
			}
		}

		public bool Jumping => Mathf.Abs(m_jumpLeft) > 0.0001f;

		public float Swell
		{
			get
			{
				if (!Calm)
				{
					return 0.2f * Mathf.Sin(SwellAngle);
				}
				return 0f;
			}
		}

		public int LowSide
		{
			get
			{
				if (!(Mathf.Abs(L) < 0.2f))
				{
					if (!(L > 0f))
					{
						return -1;
					}
					return 1;
				}
				return 0;
			}
		}

		public event Action<int> RailUnder;

		public event Action<int> RailUp;

		private static int Slot(int side)
		{
			return (side <= 0) ? 1 : 0;
		}

		public bool IsUnder(int side)
		{
			return m_under[Slot(side)];
		}

		public Band BandOf(int side)
		{
			return m_band[Slot(side)];
		}

		public void Jump(int side)
		{
			m_jumpLeft += 0.6f * Mathf.Sign((float)side);
		}

		public void Step(float dt, float coilSum)
		{
			if (dt <= 0f)
			{
				return;
			}
			float l = L;
			float num = Tuning.SwellPeriod[Mathf.Clamp(Phase, 1, 3)];
			SwellAngle += (float)Math.PI * 2f * dt / num;
			if (SwellAngle > (float)Math.PI * 2f)
			{
				SwellAngle -= (float)Math.PI * 2f;
			}
			T = (Calm ? 0f : Mathf.Clamp(coilSum + Swell, -1f, 1f));
			float num2 = Tuning.ChaseRate[Mathf.Clamp(Phase, 1, 3)];
			float num3 = Mathf.Clamp(T - L, (0f - num2) * dt, num2 * dt);
			if (Jumping)
			{
				float num4 = 2.4f;
				float num5 = Mathf.Clamp(m_jumpLeft, (0f - num4) * dt, num4 * dt);
				m_jumpLeft -= num5;
				if (num3 * num5 < 0f)
				{
					num3 = 0f;
				}
				L += num5;
			}
			L = Mathf.Clamp(L + num3, -1f, 1f);
			if ((L >= 1f || L <= -1f) && m_jumpLeft * L > 0f)
			{
				m_jumpLeft = 0f;
			}
			DLdt = (L - l) / dt;
			UpdateRail(1);
			UpdateRail(-1);
		}

		private void UpdateRail(int side)
		{
			int num = Slot(side);
			float num2 = L * (float)side;
			if (!m_under[num] && num2 >= 0.8f)
			{
				m_under[num] = true;
				this.RailUnder?.Invoke(side);
			}
			else if (m_under[num] && num2 < 0.5f)
			{
				m_under[num] = false;
				this.RailUp?.Invoke(side);
			}
			if (m_under[num])
			{
				m_band[num] = Band.Under;
			}
			else if (num2 < 0.2f)
			{
				m_band[num] = Band.Level;
			}
			else if (num2 < 0.5f)
			{
				m_band[num] = Band.Light;
			}
			else
			{
				m_band[num] = Band.Hard;
			}
		}

		public bool WouldDrown(int pinSide)
		{
			return L * (float)(-pinSide) + 0.6f >= 0.8f;
		}

		public void ResetRails()
		{
			m_under[0] = (m_under[1] = false);
		}
	}
	public sealed class HafgufaDrift : MonoBehaviour
	{
		private static readonly FieldRef<PlayerMovement, float> s_damp = AccessTools.FieldRefAccess<PlayerMovement, float>("m_dampening");

		private static readonly FieldRef<PlayerMovement, float> s_accel = AccessTools.FieldRefAccess<PlayerMovement, float>("m_accelerationFinal");

		private static readonly FieldRef<PlayerMovement, float> s_speedMax = AccessTools.FieldRefAccess<PlayerMovement, float>("m_speedMaxFinal");

		private static readonly FieldRef<PlayerMovement, float> s_friction = AccessTools.FieldRefAccess<PlayerMovement, float>("m_frictionFinal");

		private static readonly FieldRef<PlayerMovement, Vector2> s_face = AccessTools.FieldRefAccess<PlayerMovement, Vector2>("m_faceDirection");

		internal HafgufaBoss Boss;

		private readonly List<Player> m_bodies = new List<Player>();

		internal static float Impulse(float drift, float dampFace, float frictionPerSpeed, Vector2 face, float accel, float dt)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: 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_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: 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)
			if (((Vector2)(ref face)).sqrMagnitude < 0.0001f)
			{
				face = Vector2.right;
			}
			((Vector2)(ref face)).Normalize();
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(0f - face.y, face.x);
			float num = Mathf.Min((dampFace * face.x * face.x + frictionPerSpeed * val.x * val.x) * dt, 0.55f);
			if (num <= 0f)
			{
				return 0f;
			}
			float num2 = drift * num / (1f - num);
			float num3 = 0.85f * accel * dt;
			return Mathf.Clamp(num2, 0f - num3, num3);
		}

		private void FixedUpdate()
		{
			//IL_00e0: 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)
			try
			{
				if ((Object)(object)Boss == (Object)null || !Boss.DriftOn)
				{
					return;
				}
				float num = Boss.Deck.L * Tuning.DriftMax[Mathf.Clamp(((KitBoss)Boss).Phase, 1, 3)];
				if (Mathf.Abs(num) < 0.01f)
				{
					return;
				}
				Boss.LooseBodies(m_bodies);
				float fixedDeltaTime = Time.fixedDeltaTime;
				foreach (Player body in m_bodies)
				{
					PlayerMovement component = ((Component)body).GetComponent<PlayerMovement>();
					if ((Object)(object)component == (Object)null || !((Behaviour)component).enabled)
					{
						continue;
					}
					float num2 = s_speedMax.Invoke(component);
					if (!(num2 <= 0.01f))
					{
						float num3 = Impulse(num, s_damp.Invoke(component), s_friction.Invoke(component) / num2, s_face.Invoke(component), s_accel.Invoke(component), fixedDeltaTime);
						if (num3 != 0f)
						{
							component.AddImpulse(new Vector2(num3, 0f));
						}
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Ctx.Log.WarnOnce("drift", ex);
			}
		}

		internal static void Shove(List<Player> bodies, Vector2 dir, float speed, float time)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			foreach (Player body in bodies)
			{
				PlayerMovement val = (((Object)(object)body != (Object)null) ? ((Component)body).GetComponent<PlayerMovement>() : null);
				if ((Object)(object)val != (Object)null)
				{
					val.Push(((Vector2)(ref dir)).normalized * speed, time);
				}
			}
		}
	}
	internal sealed class EnvStrip
	{
		public readonly string Name;

		public readonly int Frames;

		public readonly int W;

		public readonly int H;

		public readonly float Fps;

		public readonly Anchor Anchor;

		public readonly Vector2 Offset;

		public EnvStrip(string name, int frames, int w, int h, float fps, Anchor anchor, float ox, float oy)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			Name = name;
			Frames = frames;
			W = w;
			H = h;
			Fps = fps;
			Anchor = anchor;
			Offset = new Vector2(ox, oy);
		}
	}
	internal static class EnvLayout
	{
		public static readonly EnvStrip HafgufaSea = new EnvStrip("HafgufaSea", 4, 336, 216, 4f, (Anchor)7, 0f, 0f);

		public static readonly EnvStrip HafgufaDeck = new EnvStrip("HafgufaDeck", 1, 192, 144, 1f, (Anchor)7, 0f, 0f);

		public static readonly EnvStrip HafgufaRailLap_Starboard = new EnvStrip("HafgufaRailLap_Starboard", 4, 116, 132, 6f, (Anchor)7, 0f, 0f);

		public static readonly EnvStrip HafgufaRailLap_Port = new EnvStrip("HafgufaRailLap_Port", 4, 116, 132, 6f, (Anchor)7, 0f, 0f);

		public static readonly EnvStrip HafgufaRailSpray_Starboard = new EnvStrip("HafgufaRailSpray_Starboard", 4, 116, 132, 8f, (Anchor)7, 0f, 0f);

		public static readonly EnvStrip HafgufaRailSpray_Port = new EnvStrip("HafgufaRailSpray_Port", 4, 116, 132, 8f, (Anchor)7, 0f, 0f);

		public static readonly EnvStrip HafgufaRailAwash_Starboard = new EnvStrip("HafgufaRailAwash_Starboard", 4, 116, 132, 6f, (Anchor)7, 0f, 0f);

		public static readonly EnvStrip HafgufaRailAwash_Port = new EnvStrip("HafgufaRailAwash_Port", 4, 116, 132, 6f, (Anchor)7, 0f, 0f);

		public static readonly EnvStrip HafgufaWave34_Starboard = new EnvStrip("HafgufaWave34_Starboard", 6, 46, 16, 15f, (Anchor)7, 0f, 0f);

		public static readonly EnvStrip HafgufaWave34_Port = new EnvStrip("HafgufaWave34_Port", 6, 46, 16, 15f, (Anchor)7, 0f, 0f);

		public static readonly EnvStrip HafgufaWave20_Starboard = new EnvStrip("HafgufaWave20_Starboard", 5, 46, 16, 15f, (Anchor)7, 0f, 0f);

		public static readonly EnvStrip HafgufaWave20_Port = new EnvStrip("HafgufaWave20_Port", 5, 46, 16, 15f, (Anchor)7, 0f, 0f);

		public static readonly EnvStrip HafgufaWaveFoam_Starboard = new EnvStrip("HafgufaWaveFoam_Starboard", 4, 46, 16, 6.6667f, (Anchor)7, 0f, 0f);

		public static readonly EnvStrip HafgufaWaveFoam_Port = new EnvStrip("HafgufaWaveFoam_Port", 4, 46, 16, 6.6667f, (Anchor)7, 0f, 0f);

		public static readonly EnvStrip HafgufaStreak_Right = new EnvStrip("HafgufaStreak_Right", 4, 12, 4, 8f, (Anchor)4, 0f, 0f);

		public static readonly EnvStrip HafgufaStreak_Left = new EnvStrip("HafgufaStreak_Left", 4, 12, 4, 8f, (Anchor)4, 0f, 0f);

		public static readonly EnvStrip HafgufaCleat = new EnvStrip("HafgufaCleat", 2, 14, 8, 1f, (Anchor)7, 0f, -4f);

		public static readonly EnvStrip HafgufaPin = new EnvStrip("HafgufaPin", 4, 6, 12, 1f, (Anchor)7, 0f, 0f);

		public static readonly EnvStrip HafgufaPinGreen = new EnvStrip("HafgufaPinGreen", 4, 6, 12, 1f, (Anchor)7, 0f, 0f);

		public static readonly EnvStrip HafgufaPinGreenBright = new EnvStrip("HafgufaPinGreenBright", 4, 6, 12, 1f, (Anchor)7, 0f, 0f);

		public static readonly EnvStrip HafgufaPinDrip = new EnvStrip("HafgufaPinDrip", 3, 4, 8, 8f, (Anchor)7, 0f, 0f);

		public static readonly EnvStrip HafgufaCapstan_inactive = new EnvStrip("HafgufaCapstan_inactive", 6, 36, 32, 4f, (Anchor)7, 0f, -4f);

		public static readonly EnvStrip HafgufaCapstan_activate = new EnvStrip("HafgufaCapstan_activate", 3, 36, 32, 8f, (Anchor)7, 0f, -4f);

		public static readonly EnvStrip HafgufaCapstan_active = new EnvStrip("HafgufaCapstan_active", 4, 36, 32, 6f, (Anchor)7, 0f, -4f);

		public static readonly EnvStrip HafgufaCapstan_action = new EnvStrip("HafgufaCapstan_action", 8, 36, 32, 10f, (Anchor)7, 0f, -4f);

		public static readonly EnvStrip HafgufaCapstan_deactivate = new EnvStrip("HafgufaCapstan_deactivate", 3, 36, 32, 8f, (Anchor)7, 0f, -4f);

		public static readonly EnvStrip HafgufaCapstan_greyedOut = new EnvStrip("HafgufaCapstan_greyedOut", 1, 36, 32, 6f, (Anchor)7, 0f, -4f);

		public static readonly EnvStrip HafgufaHawserMain_Starboard = new EnvStrip("HafgufaHawserMain_Starboard", 2, 48, 18, 1f, (Anchor)7, 0f, 0f);

		public static readonly EnvStrip HafgufaHawserMain_Port = new EnvStrip("HafgufaHawserMain_Port", 2, 48, 18, 1f, (Anchor)7, 0f, 0f);

		public static readonly EnvStrip HafgufaHawserFore_Starboard = new EnvStrip("HafgufaHawserFore_Starboard", 2, 40, 18, 1f, (Anchor)7, 0f, 0f);

		public static readonly EnvStrip HafgufaHawserFore_Port = new EnvStrip("HafgufaHawserFore_Port", 2, 40, 18, 1f, (Anchor)7, 0f, 0f);

		public static readonly EnvStrip HafgufaHelm_inactive = new EnvStrip("HafgufaHelm_inactive", 6, 40, 44, 8f, (Anchor)7, 0f, -3f);

		public static readonly EnvStrip HafgufaHelm_activate = new EnvStrip("HafgufaHelm_activate", 3, 40, 44, 8f, (Anchor)7, 0f, -3f);

		public static readonly EnvStrip HafgufaHelm_active = new EnvStrip("HafgufaHelm_active", 4, 40, 44, 6f, (Anchor)7, 0f, -3f);

		public static readonly EnvStrip HafgufaHelm_action = new EnvStrip("HafgufaHelm_action", 8, 40, 44, 10f, (Anchor)7, 0f, -3f);

		public static readonly EnvStrip HafgufaHelm_actionPort = new EnvStrip("HafgufaHelm_actionPort", 8, 40, 44, 10f, (Anchor)7, 0f, -3f);

		public static readonly EnvStrip HafgufaHelm_deactivate = new EnvStrip("HafgufaHelm_deactivate", 3, 40, 44, 8f, (Anchor)7, 0f, -3f);

		public static readonly EnvStrip HafgufaHelm_greyedOut = new EnvStrip("HafgufaHelm_greyedOut", 1, 40, 44, 6f, (Anchor)7, 0f, -3f);

		public static readonly EnvStrip HafgufaHelmLash = new EnvStrip("HafgufaHelmLash", 3, 32, 32, 6f, (Anchor)7, 0f, 7f);

		public static readonly EnvStrip HafgufaGunR_inactive = new EnvStrip("HafgufaGunR_inactive", 6, 34, 30, 4f, (Anchor)7, 8f, -2f);

		public static readonly EnvStrip HafgufaGunR_activate = new EnvStrip("HafgufaGunR_activate", 3, 34, 30, 8f, (Anchor)7, 8f, -2f);

		public static readonly EnvStrip HafgufaGunR_active = new EnvStrip("HafgufaGunR_active", 4, 34, 30, 6f, (Anchor)7, 8f, -2f);

		public static readonly EnvStrip HafgufaGunR_action = new EnvStrip("HafgufaGunR_action", 9, 34, 30, 7.5f, (Anchor)7, 8f, -2f);

		public static readonly EnvStrip HafgufaGunR_deactivate = new EnvStrip("HafgufaGunR_deactivate", 3, 34, 30, 8f, (Anchor)7, 8f, -2f);

		public static readonly EnvStrip HafgufaGunR_greyedOut = new EnvStrip("HafgufaGunR_greyedOut", 1, 34, 30, 6f, (Anchor)7, 8f, -2f);

		public static readonly EnvStrip HafgufaGunL_inactive = new EnvStrip("HafgufaGunL_inactive", 6, 34, 30, 4f, (Anchor)7, -8f, -2f);

		public static readonly EnvStrip HafgufaGunL_activate = new EnvStrip("HafgufaGunL_activate", 3, 34, 30, 8f, (Anchor)7, -8f, -2f);

		public static readonly EnvStrip HafgufaGunL_active = new EnvStrip("HafgufaGunL_active", 4, 34, 30, 6f, (Anchor)7, -8f, -2f);

		public static readonly EnvStrip HafgufaGunL_action = new EnvStrip("HafgufaGunL_action", 9, 34, 30, 7.5f, (Anchor)7, -8f, -2f);

		public static readonly EnvStrip HafgufaGunL_deactivate = new EnvStrip("HafgufaGunL_deactivate", 3, 34, 30, 8f, (Anchor)7, -8f, -2f);

		public static readonly EnvStrip HafgufaGunL_greyedOut = new EnvStrip("HafgufaGunL_greyedOut", 1, 34, 30, 6f, (Anchor)7, -8f, -2f);

		public static readonly EnvStrip HafgufaGunUp_inactive = new EnvStrip("HafgufaGunUp_inactive", 6, 34, 30, 4f, (Anchor)7, 0f, -2f);

		public static readonly EnvStrip HafgufaGunUp_activate = new EnvStrip("HafgufaGunUp_activate", 3, 34, 30, 8f, (Anchor)7, 0f, -2f);

		public static readonly EnvStrip HafgufaGunUp_active = new EnvStrip("HafgufaGunUp_active", 4, 34, 30, 6f, (Anchor)7, 0f, -2f);

		public static readonly EnvStrip HafgufaGunUp_action = new EnvStrip("HafgufaGunUp_action", 9, 34, 30, 7.5f, (Anchor)7, 0f, -2f);

		public static readonly EnvStrip HafgufaGunUp_deactivate = new EnvStrip("HafgufaGunUp_deactivate", 3, 34, 30, 8f, (Anchor)7, 0f, -2f);

		public static readonly EnvStrip HafgufaGunUp_greyedOut = new EnvStrip("HafgufaGunUp_greyedOut", 1, 34, 30, 6f, (Anchor)7, 0f, -2f);

		public static readonly EnvStrip HafgufaCannonball = new EnvStrip("HafgufaCannonball", 4, 8, 8, 12f, (Anchor)4, 0f, 0f);

		public static readonly EnvStrip HafgufaForemast = new EnvStrip("HafgufaForemast", 1, 12, 96, 1f, (Anchor)7, 0f, -3f);

		public static readonly EnvStrip HafgufaMainmast = new EnvStrip("HafgufaMainmast", 1, 12, 36, 1f, (Anchor)7, 0f, -3f);

		public static readonly EnvStrip HafgufaLantern = new EnvStrip("HafgufaLantern", 7, 26, 20, 1f, (Anchor)1, 0f, 0f);

		public static readonly EnvStrip[] All = new EnvStrip[61]
		{
			HafgufaSea, HafgufaDeck, HafgufaRailLap_Starboard, HafgufaRailLap_Port, HafgufaRailSpray_Starboard, HafgufaRailSpray_Port, HafgufaRailAwash_Starboard, HafgufaRailAwash_Port, HafgufaWave34_Starboard, HafgufaWave34_Port,
			HafgufaWave20_Starboard, HafgufaWave20_Port, HafgufaWaveFoam_Starboard, HafgufaWaveFoam_Port, HafgufaStreak_Right, HafgufaStreak_Left, HafgufaCleat, HafgufaPin, HafgufaPinGreen, HafgufaPinGreenBright,
			HafgufaPinDrip, HafgufaCapstan_inactive, HafgufaCapstan_activate, HafgufaCapstan_active, HafgufaCapstan_action, HafgufaCapstan_deactivate, HafgufaCapstan_greyedOut, HafgufaHawserMain_Starboard, HafgufaHawserMain_Port, HafgufaHawserFore_Starboard,
			HafgufaHawserFore_Port, HafgufaHelm_inactive, HafgufaHelm_activate, HafgufaHelm_active, HafgufaHelm_action, HafgufaHelm_actionPort, HafgufaHelm_deactivate, HafgufaHelm_greyedOut, HafgufaHelmLash, HafgufaGunR_inactive,
			HafgufaGunR_activate, HafgufaGunR_active, HafgufaGunR_action, HafgufaGunR_deactivate, HafgufaGunR_greyedOut, HafgufaGunL_inactive, HafgufaGunL_activate, HafgufaGunL_active, HafgufaGunL_action, HafgufaGunL_deactivate,
			HafgufaGunL_greyedOut, HafgufaGunUp_inactive, HafgufaGunUp_activate, HafgufaGunUp_active, HafgufaGunUp_action, HafgufaGunUp_deactivate, HafgufaGunUp_greyedOut, HafgufaCannonball, HafgufaForemast, HafgufaMainmast,
			HafgufaLantern
		};
	}
	internal static class Fx
	{
		private static readonly FieldRef<PropTrap, List<AttackData>> s_trapAttacks = AccessTools.FieldRefAccess<PropTrap, List<AttackData>>("m_attacks");

		private static readonly FieldRef<PropTrap, float[]> s_angleList = AccessTools.FieldRefAccess<PropTrap, float[]>("m_attackAnglesList");

		private static readonly FieldRef<Player, exSpriteAnimClip> s_idle = AccessTools.FieldRefAccess<Player, exSpriteAnimClip>("m_animationIdle");

		public static void SetLiveCooldown(PropTrap trap, float cooldown)
		{
			if ((Object)(object)trap == (Object)null)
			{
				return;
			}
			List<AttackData> list = s_trapAttacks.Invoke(trap);
			if (list == null)
			{
				return;
			}
			foreach (AttackData item in list)
			{
				if (item != null)
				{
					item.m_cooldown = cooldown;
				}
			}
		}

		public static void SetAngleList(PropTrap trap, float[] angles)
		{
			if ((Object)(object)trap != (Object)null)
			{
				s_angleList.Invoke(trap) = angles;
			}
		}

		public static float[] GetAngleList(PropTrap trap)
		{
			if (!((Object)(object)trap != (Object)null))
			{
				return null;
			}
			return s_angleList.Invoke(trap);
		}

		public static void SetIdle(KitBody body, exSpriteAnimClip clip)
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Invalid comparison between Unknown and I4
			if ((Object)(object)body == (Object)null || (Object)(object)body.Player == (Object)null || (Object)(object)clip == (Object)null || !body.Alive || (Object)(object)s_idle.Invoke(body.Player) == (Object)(object)clip)
			{
				return;
			}
			s_idle.Invoke(body.Player) = clip;
			if ((int)body.Player.GetState() == 2 && (Object)(object)body.Anim != (Object)null)
			{
				if (body.Anim.GetAnimation(((Object)clip).name) == null)
				{
					body.Anim.AddAnimation(clip);
				}
				body.Anim.Play(((Object)clip).name);
			}
		}

		public static void Show(exSprite sprite, bool on)
		{
			if ((Object)(object)sprite != (Object)null && ((Behaviour)sprite).enabled != on)
			{
				((Behaviour)sprite).enabled = on;
			}
		}

		public static void EnsureCueSource(GameObject go)
		{
			if ((Object)(object)go != (Object)null && (Object)(object)go.GetComponent<AudioCueSource>() == (Object)null)
			{
				go.AddComponent<AudioCueSource>();
			}
		}

		public static string SetDamageBox(GameObject fx, Vector2 size, Vector2 centre)
		{
			//IL_00a7: 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_00b8: 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_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			List<string> list = new List<string>();
			Collider[] componentsInChildren = fx.GetComponentsInChildren<Collider>(true);
			foreach (Collider val in componentsInChildren)
			{
				list.Add(((object)val).GetType().Name + "@" + ((Object)((Component)val).gameObject).name + " layer " + ((Component)val).gameObject.layer + (val.isTrigger ? " trigger" : " solid"));
				Object.DestroyImmediate((Object)(object)val);
			}
			fx.layer = 13;
			BoxCollider obj = fx.AddComponent<BoxCollider>();
			((Collider)obj).isTrigger = true;
			obj.size = new Vector3(size.x, size.y, 50f);
			obj.center = new Vector3(centre.x, centre.y, 0f);
			if (list.Count != 0)
			{
				return string.Join(", ", list.ToArray());
			}
			return "no collider";
		}

		public static void AuditDamage(GameObject fx)
		{
			DamageEffect component = fx.GetComponent<DamageEffect>();
			if ((Object)(object)component == (Object)null)
			{
				throw new InvalidOperationException(((Object)fx).name + " has no DamageEffect");
			}
			if (component.m_contactData == null || component.m_contactData.Count == 0)
			{
				throw new InvalidOperationException(((Object)fx).name + " has no contact data");
			}
			foreach (ContactData contactDatum in component.m_contactData)
			{
				if (contactDatum != null && contactDatum.m_hitFriendly)
				{
					throw new InvalidOperationException(((Object)fx).name + " has a contact that hits friends");
				}
			}
			Util.Field(typeof(DamageEffect), "m_status").SetValue(component, null);
			Util.Field(typeof(DamageEffect), "m_statusChance").SetValue(component, 0f);
			component.m_spawnOnHit = null;
		}

		public static void FixEffectStart(GameObject fx)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Expected O, but got Unknown
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Expected O, but got Unknown
			Effect component = fx.GetComponent<Effect>();
			if (!((Object)(object)component == (Object)null))
			{
				Util.Field(typeof(Effect), "m_startFrame").SetValue(component, (object?)new MinMaxRange(0f));
				Util.Field(typeof(Effect), "m_offsetX").SetValue(component, (object?)new MinMaxRange(0f));
				Util.Field(typeof(Effect), "m_offsetY").SetValue(component, (object?)new MinMaxRange(0f));
				Util.Field(typeof(Effect), "m_alsoSpawn").SetValue(component, null);
			}
		}

		public static void SetOnlyClip(GameObject fx, exSpriteAnimClip clip)
		{
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			exSpriteAnimation component = fx.GetComponent<exSpriteAnimation>();
			exSprite component2 = fx.GetComponent<exSprite>();
			if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null)
			{
				throw new InvalidOperationException(((Object)fx).name + " has no exSprite or exSpriteAnimation");
			}
			component.animations = new List<exSpriteAnimClip> { clip };
			component.defaultAnimation = clip;
			Effect component3 = fx.GetComponent<Effect>();
			if ((Object)(object)component3 != (Object)null)
			{
				Util.Field(typeof(Effect), "m_animationDefault").SetValue(component3, null);
				Util.Field(typeof(Effect), "m_angleAnimations").SetValue(component3, new List<AnimAngle>());
			}
			component2.SetSprite(clip.frameInfos[0].atlas, clip.frameInfos[0].index, true);
			((exPlane)component2).anchor = (Anchor)4;
			((exPlane)component2).offset = Vector2.zero;
		}

		public static float Sign(float x)
		{
			if (!(x >= 0f))
			{
				return -1f;
			}
			return 1f;
		}
	}
	public sealed class HafgufaBoss : KitBoss
	{
		internal readonly CleatState[] Board = new CleatState[Layout.Cleats.Length];

		internal readonly DeckList Deck = new DeckList();

		internal KrakenHold Hold;

		private readonly Cleat[] m_cleats = new Cleat[Layout.Cleats.Length];

		private readonly ArmVisual[] m_arms = new ArmVisual[3];

		internal HeadController Head;

		private LashAttack m_lash;

		private GreenWater m_green;

		internal Overlays Overlays;

		private HelmStation m_helm;

		private readonly List<CapstanStation> m_capstans = new List<CapstanStation>();

		private readonly List<GunStation> m_guns = new List<GunStation>();

		private HafgufaDrift m_drift;

		private readonly List<exSprite> m_hiddenArt = new List<exSprite>();

		private readonly List<Player> m_scratch = new List<Player>();

		internal bool BowAwake;

		internal int HeroSide = 1;

		internal Vector2 HeroLocal;

		private bool m_heroAlive;

		private bool m_beat;

		private float m_beatTimer;

		private bool m_fallback;

		private float m_fallbackTimer;

		private float m_time;

		private bool m_ended;

		private int m_roomId;

		private static readonly Vector2 WeakpointOffset = new Vector2(5f, -10f);

		protected override Vector2 BarLocal => Layout.Bar;

		internal bool DriftOn
		{
			get
			{
				if (((KitBoss)this).Fighting && !m_beat && !m_ended && m_heroAlive)
				{
					return !m_fallback;
				}
				return false;
			}
		}

		internal bool PinsLive
		{
			get
			{
				if (((KitBoss)this).Fighting && !m_beat && !m_ended)
				{
					return m_heroAlive;
				}
				return false;
			}
		}

		internal GameObject DamageOwner
		{
			get
			{
				if (!((Object)(object)((KitBoss)this).LifeBody != (Object)null) || !((KitBoss)this).LifeBody.Alive)
				{
					return ((Component)this).gameObject;
				}
				return ((Component)((KitBoss)this).LifeBody).gameObject;
			}
		}

		private void InitLogic()
		{
			if (Hold == null)
			{
				for (int i = 0; i < Board.Length; i++)
				{
					Board[i] = new CleatState
					{
						Index = i,
						Side = Layout.SideOf(i),
						Awake = !Layout.IsBow(i)
					};
				}
				Hold = new KrakenHold(Board, Deck);
				Hold.Changed += OnArmChanged;
				Hold.HeaveStarted += OnHeaveStarted;
				Deck.RailUnder += OnRailUnder;
			}
		}

		protected override void BuildArena(Room room)
		{
			//IL_001a: 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_00a9: 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_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: 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_0216: Unknown result type (might be due to invalid IL or missing references)
			//IL_022a: Unknown result type (might be due to invalid IL or missing references)
			//IL_022f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0233: Unknown result type (might be due to invalid IL or missing references)
			//IL_0238: Unknown result type (might be due to invalid IL or missing references)
			//IL_023d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0241: Unknown result type (might be due to invalid IL or missing references)
			//IL_0254: Unknown result type (might be due to invalid IL or missing references)
			//IL_0259: 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_0267: Unknown result type (might be due to invalid IL or missing references)
			//IL_026b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0277: Unknown result type (might be due to invalid IL or missing references)
			//IL_027c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0281: Unknown result type (might be due to invalid IL or missing references)
			//IL_0295: Unknown result type (might be due to invalid IL or missing references)
			//IL_029a: Unknown result type (might be due to invalid IL or missing references)
			//IL_029f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cf: 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)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0339: Unknown result type (might be due to invalid IL or missing references)
			//IL_033e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0343: Unknown result type (might be due to invalid IL or missing references)
			//IL_034e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0355: Unknown result type (might be due to invalid IL or missing references)
			//IL_0365: Unknown result type (might be due to invalid IL or missing references)
			//IL_0366: Unknown result type (might be due to invalid IL or missing references)
			//IL_037a: Expected O, but got Unknown
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_04cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_04fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_050f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0525: Unknown result type (might be due to invalid IL or missing references)
			//IL_052b: Unknown result type (might be due to invalid IL or missing references)
			//IL_053f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0555: Unknown result type (might be due to invalid IL or missing references)
			//IL_055b: Unknown result type (might be due to invalid IL or missing references)
			//IL_056f: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03de: Unknown result type (might be due to invalid IL or missing references)
			//IL_05cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_05d5: Expected O, but got Unknown
			//IL_03ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_040b: Unknown result type (might be due to invalid IL or missing references)
			//IL_040c: Unknown result type (might be due to invalid IL or missing references)
			//IL_041b: Unknown result type (might be due to invalid IL or missing references)
			//IL_042f: Unknown result type (might be due to invalid IL or missing references)
			//IL_043a: Unknown result type (might be due to invalid IL or missing references)
			//IL_044d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0460: Unknown result type (might be due to invalid IL or missing references)
			//IL_0473: Unknown result type (might be due to invalid IL or missing references)
			//IL_048b: Expected O, but got Unknown
			InitLogic();
			HideColosseumArt(room);
			Sheet envSheet = Templates.EnvSheet;
			((Object)((Component)Floor(room, EnvLayout.HafgufaSea, Layout.Sea, 99f, play: true)).gameObject).name = "HafgufaSea";
			((Object)((Component)Floor(room, EnvLayout.HafgufaDeck, Layout.Deck, 98f, play: false)).gameObject).name = "HafgufaDeck";
			m_roomId = ((Object)room).GetInstanceID();
			if (KrakenPatches.Active)
			{
				KrakenPatches.SetHull(room, Layout.DeckHull);
			}
			else
			{
				((KitBoss)this).Ctx.Log.Warn("Hafgufa's pathfinder patch is not active: the bot hero keeps the room's own outline");
			}
			KitRoom.AddWall(room, new Rect(88f, -67f, 6f, 89f), "HafgufaRailStarboard", 9, true);
			KitRoom.AddWall(room, new Rect(-94f, -67f, 6f, 89f), "HafgufaRailPort", 9, true);
			Transform parent = (((Object)(object)room.m_wallContainer != (Object)null) ? room.m_wallContainer.transform : ((Component)room).transform);
			if ((Object)(object)room.m_wallContainer == (Object)null)
			{
				((KitBoss)this).Ctx.Log.Warn("The arena has no wall container; the bow rails join the pathfinder as boxes");
			}
			Vector2 val = default(Vector2);
			Vector2 val2 = default(Vector2);
			for (int i = -1; i <= 1; i += 2)
			{
				((Vector2)(ref val))..ctor(Layout.BowRailFrom.x * (float)i, Layout.BowRailFrom.y);
				((Vector2)(ref val2))..ctor(Layout.BowRailTo.x * (float)i, Layout.BowRailTo.y);
				Vector2 val3 = OutwardOf(val, val2);
				RotatedBox(parent, room, "HafgufaBowRail" + ((i > 0) ? "Starboard" : "Port"), val, val2, 6f, val3, 9);
				RotatedBox(parent, room, "HafgufaBowSea" + ((i > 0) ? "Starboard" : "Port"), val + val3 * 6f, val2 + val3 * 6f, 30f, val3, 4);
			}
			Box(parent, room, "HafgufaStem", Layout.StemCentre, Layout.StemSize, 9);
			Rect val4 = Layout.SeaStripStarboard;
			Vector2 center = ((Rect)(ref val4)).center;
			val4 = Layout.SeaStripStarboard;
			Box(parent, room, "HafgufaSeaStarboard", center, ((Rect)(ref val4)).size, 4);
			val4 = Layout.SeaStripPort;
			Vector2 center2 = ((Rect)(ref val4)).center;
			val4 = Layout.SeaStripPort;
			Box(parent, room, "HafgufaSeaPort", center2, ((Rect)(ref val4)).size, 4);
			KitRoom.AddWall(room, CentredRect(Layout.Foremast, Layout.MastCollider), "HafgufaForemastCell", 9, true);
			KitRoom.AddWall(room, CentredRect(Layout.Mainmast, Layout.MastCollider), "HafgufaMainmastCell", 9, true);
			Standing(room, EnvLayout.HafgufaForemast, Layout.Foremast, 0f);
			Standing(room, EnvLayout.HafgufaMainmast, Layout.Mainmast, 0f);
			for (int j = 0; j < Board.Length; j++)
			{
				Cleat cleat = new Cleat(this, room, Board[j], envSheet);
				cleat.Blow += OnBlow;
				m_cleats[j] = cleat;
			}
			Overlays = new Overlays(this, room);
			KitStation st = ((KitBoss)this).SpawnStation(Templates.Helm, Layout.Helm, new StationSpec
			{
				Kind = "Helm",
				HumanOnly = true,
				AimInitial = 0f,
				DrawnSeatLocal = Layout.HelmSeat
			});
			m_helm = new HelmStation(this, st, room);
			m_helm.SetPhase(1);
			for (int k = 0; k < Layout.Capstans.Length; k++)
			{
				int num = k;
				CapstanStation cap = null;
				int cleat2 = ((k % 2 == 0) ? 1 : 4);
				KitStation st2 = ((KitBoss)this).SpawnStation(Templates.Capstan, Layout.Capstans[k], new StationSpec
				{
					Kind = "Capstan",
					WakePhase = ((k < 2) ? 1 : 2),
					WakeByBoss = (k >= 2),
					BlockerLocal = Layout.CapstanBlocker,
					DrawnSeatLocal = Layout.CapstanSeat,
					AimInitial = Layout.Bearing(num, cleat2),
					ExitAfterIdle = 4f,
					CanHit = (KitStation val6, Player h) => cap != null && cap.BotCanHit(),
					ShouldEnter = (KitStation val6, Player h) => cap != null && cap.Job() >= 0,
					ShouldExit = (KitStation val6, Player h) => cap == null || cap.BotShouldExit(),
					BotAim = (KitStation val6, Player h) => (cap == null) ? ((Vector2?)null) : cap.BotAim()
				});
				cap = new CapstanStation(this, st2, num, room);
				m_capstans.Add(cap);
			}
			AddGun(Templates.GunR, Layout.GunR, 1, Layout.GunSideSeat, 16f, new Vector2(-60f, 60f));
			AddGun(Templates.GunL, Layout.GunL, 1, Layout.GunSideSeat, 16f, new Vector2(120f, 240f));
			AddGun(Templates.GunUp, Layout.GunsUp[0], 2, Layout.GunUpSeat, 10f, new Vector2(30f, 150f));
			AddGun(Templates.GunUp, Layout.GunsUp[1], 2, Layout.GunUpSeat, 10f, new Vector2(30f, 150f));
			for (int num2 = 0; num2 < m_arms.Length; num2++)
			{
				m_arms[num2] = new ArmVisual(this, room, "HafgufaArm" + num2);
			}
			m_lash = new LashAttack(this, room);
			m_green = new GreenWater(this);
			GameObject val5 = new GameObject("HafgufaDrift");
			val5.transform.SetParent(((Component)this).transform, false);
			m_drift = val5.AddComponent<HafgufaDrift>();
			m_drift.Boss = this;
			((KitBoss)this).Ctx.Log.Info("Hafgufa arena: " + m_hiddenArt.Count + " colosseum sprites hidden, " + m_cleats.Length + " cleats, " + (1 + m_capstans.Count + m_guns.Count) + " stations");
		}

		private void AddGun(GameObject template, Vector2 at, int wakePhase, Vector2 seat, float muzzle, Vector2 arc)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: 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_003e: 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_004c: 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_0069: 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_0092: Expected O, but got Unknown
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			GunStation gun = null;
			KitStation st = ((KitBoss)this).SpawnStation(template, at, new StationSpec
			{
				Kind = "Gun",
				WakePhase = wakePhase,
				WakeByBoss = (wakePhase > 1),
				DrawnSeatLocal = seat,
				ApplyBossDamage = true,
				LineOfSight = true,
				ExitAfterIdle = 2.5f,
				CanHit = (KitStation k, Player h) => gun != null && gun.BotCanHit(h),
				ShouldEnter = (KitStation k, Player h) => gun != null && gun.BotShouldEnter(h),
				BotAim = (KitStation k, Player h) => (gun == null) ? ((Vector2?)null) : gun.BotAim(h)
			});
			gun = new GunStation(this, st)
			{
				Seat = seat,
				Muzzle = muzzle,
				Arc = arc
			};
			m_guns.Add(gun);
		}

		private void HideColosseumArt(Room room)
		{
			//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_0033: 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_003c: 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_0056: 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)
			//IL_0070: 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_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			Vector3 position = ((Component)room).transform.position;
			exSprite[] componentsInChildren = ((Component)room).GetComponentsInChildren<exSprite>(true);
			foreach (exSprite val in componentsInChildren)
			{
				Renderer component = ((Component)val).GetComponent<Renderer>();
				if ((Object)(object)component != (Object)null)
				{
					Bounds bounds = component.bounds;
					if (((Bounds)(ref bounds)).max.x - position.x >= 37f && ((Bounds)(ref bounds)).min.x - position.x <= 53f && ((Bounds)(ref bounds)).min.y - position.y <= -60f)
					{
						Vector3 size = ((Bounds)(ref bounds)).size;
						if (((Vector3)(ref size)).sqrMagnitude > 0.01f)
						{
							continue;
						}
					}
				}
				m_hiddenArt.Add(val);
				((Behaviour)val).enabled = false;
			}
		}

		private exSprite Floor(Room room, EnvStrip strip, Vector2 local, float z, bool play)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: 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_0072: 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)
			exSprite val = KitArt.CreateSprite(((Component)room).transform, Templates.EnvSheet, strip.Name, 0, ((KitBoss)this).World(local), strip.Anchor, false, 0f);
			((exPlane)val).offset = strip.Offset;
			if (strip.Frames > 1)
			{
				KitArt.Animate(val, (IEnumerable<exSpriteAnimClip>)null, Templates.Env[strip.Name], play);
			}
			Vector3 position = ((Component)val).transform.position;
			((Component)val).transform.position = new Vector3(position.x, position.y, z);
			return val;
		}

		private void Standing(Room room, EnvStrip strip, Vector2 local, float height)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: 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)
			exSprite obj = KitArt.CreateSprite(((Component)room).transform, Templates.EnvSheet, strip.Name, 0, ((KitBoss)this).World(local), strip.Anchor, true, height);
			((exPlane)obj).offset = strip.Offset;
			((Object)((Component)obj).gameObject).name = strip.Name;
		}

		private static Rect CentredRect(Vector2 c, Vector2 size)
		{
			//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_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: 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_0032: Unknown result type (might be due to invalid IL or missing references)
			return new Rect(c.x - size.x * 0.5f, c.y - size.y * 0.5f, size.x, size.y);
		}

		private static Vector2 OutwardOf(Vector2 a, Vector2 b)
		{
			//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_0007: 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_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: 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_0035: 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_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: 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_0058: 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)
			Vector2 val = b - a;
			Vector2 normalized = ((Vector2)(ref val)).normalized;
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(0f - normalized.y, normalized.x);
			Vector2 val3 = (a + b) * 0.5f;
			if (Vector2.Dot(val2, val3 - new Vector2(0f, 0f)) < 0f)
			{
				val2 = -val2;
				return val2;
			}
			return val2;
		}

		private void RotatedBox(Transform parent, Room room, string name, Vector2 a, Vector2 b, float width, Vector2 outward, int layer)
		{
			//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_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: 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_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_006f: 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_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name)
			{
				layer = layer
			};
			val.transform.SetParent(parent, false);
			Vector2 val2 = (a + b) * 0.5f + outward * (width * 0.5f);
			val.transform.position = ((KitBoss)this).World(val2);
			Vector2 val3 = b - a;
			val.transform.rotation = Quaternion.Euler(0f, 0f, Mathf.Atan2(val3.y, val3.x) * 57.29578f);
			val.transform.localScale = Vector3.one;
			val.AddComponent<BoxCollider>().size = new Vector3(((Vector2)(ref val3)).magnitude + width, width, 50f);
		}

		private void Box(Transform parent, Room room, string name, Vector2 centre, Vector2 size, int layer)
		{
			//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_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name)
			{
				layer = layer
			};
			val.transform.SetParent(parent, false);
			val.transform.position = ((KitBoss)this).World(centre);
			val.transform.rotation = Quaternion.identity;
			val.transform.localScale = Vector3.one;
			val.AddComponent<BoxCollider>().size = new Vector3(size.x, size.y, 50f);
		}

		protected override KitBody SpawnBodies(Room room)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			InitLogic();
			KitBody val = KitBodies.Spawn<KrakenBrain>((KitBoss)(object)this, Templates.Head, Layout.HeadIntroPivot, "Hafgufa");
			val.SetHurtSound(SoundSet.Hurt, 0.25f);
			val.RefuseStatuses = true;
			Head = new HeadController(this, val, room);
			DelistHead();
			if (((KitBoss)this).ArenaFailed || m_cleats[0] == null)
			{
				m_fallback = true;
				((KitBoss)this).Ctx.Log.Error("Hafgufa's arena did not build: the head surfaces on its own so the fight stays winnable");
			}
			return val;
		}

		private void DelistHead()
		{
			if (Head != null && !((Object)(object)Head.Body == (Object)null))
			{
				SystemLevel get = Singleton<SystemLevel>.Get;
				List<GameObject> list = (((Object)(object)get != (Object)null) ? get.GetMonstersSpawned() : null);
				GameObject gameObject = ((Component)Head.Body).gameObject;
				if (list != null && list.Contains(gameObject))
				{
					get.OnMonsterDespawned(gameObject);
				}
			}
		}

		protected override IEnumerator Intro()
		{
			UpdateHero();
			Hold.HeroSide = HeroSide;
			Hold.HeroY = HeroLocal.y;
			Hold.HeroX = HeroLocal.x;
			List<int> want = Hold.Wanted();
			for (int i = 0; i < Hold.Arms.Length && i < want.Count; i++)
			{
				Hold.TryWrap(Hold.Arms[i], want[i]);
				yield return (object)new WaitForSeconds(0.25f);
				if (i == 0 && Head != null)
				{
					Head.IntroSurface();
				}
			}
			if (Head != null && Head.State == HeadState.Down)
			{
				Head.IntroSurface();
			}
			yield return (object)new WaitForSeconds(2.45f);
		}

		protected override void OnFightStart()
		{
			m_time = 0f;
			Hold.ResetTimers();
			if (m_lash != null)
			{
				m_lash.Schedule(1, soon: true);
			}
			if ((Object)(object)m_drift != (Object)null)
			{
				((Behaviour)m_drift).enabled = true;
			}
			KitSelfTest.Note("hafgufa fight: L " + Deck.L.ToString("0.00") + ", coils " + CoilCount());
		}

		protected override void OnPhase(int phase)
		{
			Deck.Phase = phase;
			if (m_helm != null)
			{
				m_helm.SetPhase(phase);
			}
			switch (phase)
			{
			case 2:
			{
				m_beat = true;
				m_beatTimer = 2.4f;
				foreach (CapstanStation capstan in m_capstans)
				{
					capstan.RefundIfWindingUp();
				}
				foreach (GunStation gun in m_guns)
				{
					gun.RefundIfWindingUp();
				}
				((KitBoss)this).SetStationsSuspended(true);
				if (m_lash != null)
				{
					m_lash.Cancel();
				}
				if (m_green != null)
				{
					m_green.Reset();
				}
				Hold.LetGoAll();
				foreach (CapstanStation capstan2 in m_capstans)
				{
					ReleaseCapstanCoil(capstan2);
				}
				CleatState[] board = Board;
				for (int i = 0; i < board.Length; i++)
				{
					board[i].Blows = 0;
				}
				Deck.Calm = true;
				if (Head != null)
				{
					Head.Roar(HeadState.Dive);
				}
				break;
			}
			case 3:
				if (Head != null)
				{
					Head.SetRide(ride: true);
					if (Head.State == HeadState.Up || Head.State == HeadState.Heave)
					{
						Head.Roar(HeadState.Up);
					}
				}
				break;
			}
		}

		private void EndPhase2Beat()
		{
			m_beat = false;
			if (m_ended || ((KitBoss)this).Won || ((KitBoss)this).Killed)
			{
				return;
			}
			((KitBoss)this).WakeStations(2);
			BowAwake = true;
			for (int i = 0; i < Board.Length; i++)
			{
				if (Layout.IsBow(i) && m_cleats[i] != null)
				{
					m_cleats[i].Wake();
				}
				else if (Layout.IsBow(i))
				{
					Board[i].Awake = true;
				}
			}
			foreach (CapstanStation capstan in m_capstans)
			{
				capstan.WakeBow();
			}
			Deck.Calm = false;
			((KitBoss)this).SetStationsSuspended(false);
			Hold.ResetTimers();
			if (m_lash != null)
			{
				m_lash.Schedule(2, soon: false);
			}
			KitSelfTest.Note("phase 2 beat over: bow cleats, fore capstans and stern guns awake");
		}

		protected override void OnBossDying(DamageInfo info)
		{
			m_ended = true;
			m_beat = false;
			if (Head != null)
			{
				Head.Die();
			}
			Hold.Enabled = false;
			Deck.Calm = true;
			if (m_lash != null)
			{
				m_lash.Cancel();
			}
			if ((Object)(object)m_drift != (Object)null)
			{
				((Behaviour)m_drift).enabled = false;
			}
		}

		protected override void OnHeroKilledKit(Player hero)
		{
			m_ended = true;
			m_beat = false;
			Hold.Enabled = false;
			if ((Object)(object)m_drift != (Object)null)
			{
				((Behaviour)m_drift).enabled = false;
			}
			if (m_lash != null)
			{
				m_lash.Cancel();
			}
			if (Head != null)
			{
				Head.ReleaseFilter();
				if (Head.State == HeadState.Up)
				{
					Head.Roar(HeadState.Up);
				}
			}
		}

		protected override void OnFrozen(bool frozen)
		{
			if ((Object)(object)m_drift != (Object)null)
			{
				((Behaviour)m_drift).enabled = !frozen && !m_ended;
			}
		}

		protected override void OnCleanup()
		{
			KrakenPatches.ClearHull(m_roomId);
			if (Head != null)
			{
				Head.ReleaseFilter();
			}
		}

		protected override void KitUpdate()
		{
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0204: Unknown result type (might be due to invalid IL or missing references)
			float deltaTime = Time.deltaTime;
			if (deltaTime <= 0f || Hold == null)
			{
				return;
			}
			m_time += deltaTime;
			DelistHead();
			UpdateHero();
			bool flag = ((KitBoss)this).Fighting && !m_beat && !m_ended && m_heroAlive;
			if (m_beat && !m_ended)
			{
				m_beatTimer -= deltaTime;
				if (m_beatTimer <= 0f)
				{
					EndPhase2Beat();
				}
			}
			Hold.HeroSide = HeroSide;
			Hold.HeroY = HeroLocal.y;
			Hold.HeroX = HeroLocal.x;
			Hold.HeadAway = Head != null && !Head.Riding && (Head.State == HeadState.Down || Head.State == HeadState.Resting);
			Hold.Riding = Head != null && Head.Riding;
			Hold.Enabled = flag && !m_fallback;
			Hold.Step(deltaTime);
			Deck.Phase = ((KitBoss)this).Phase;
			Deck.Step(deltaTime, Hold.ActiveSum());
			if (Head != null)
			{
				if (m_fallback && flag)
				{
					FallbackStep(deltaTime);
				}
				Head.Step(deltaTime, HeroLocal, SomeoneNear());
			}
			Player val = Util.Hero();
			Vector2 p = (Vector2)(((Object)(object)val != (Object)null) ? ((KitBoss)this).RoomLocal(((Component)val).transform.position) : new Vector2(9999f, 9999f));
			bool flag2 = IsBotHero(val);
			int num = (flag2 ? BotPinTarget() : (-1));
			for (int i = 0; i < Board.Length; i++)
			{
				CleatState cleatState = Board[i];
				bool flag3 = ((!flag2) ? (!Layout.InFoothold(i, p)) : (i != num && m_time - cleatState.LastBlow > 2f));
				if (cleatState.Blows > 0 && (!cleatState.Held || flag3))
				{
					cleatState.Blows = 0;
				}
				bool flag4 = PinCovered(i);
				bool green = flag && cleatState.Held && cleatState.Awake && Deck.WouldDrown(cleatState.Side) && !Deck.IsUnder(-cleatState.Side) && (Head == null || !Head.Resting) && !flag4 && Hold.PullFrees(i);
				if (m_cleats[i] != null)
				{
					m_cleats[i].Refresh(green, flag4, m_time);
				}
			}
			ArmVisual[] arms = m_arms;
			for (int j = 0; j < arms.Length; j++)
			{
				arms[j]?.Tick(deltaTime);
			}
			if (m_lash != null)
			{
				m_lash.Step(deltaTime, flag && !m_fallback);
			}
			if (m_green != null)
			{
				m_green.Step(deltaTime, flag && !m_fallback);
			}
			if (m_helm != null)
			{
				m_helm.Tick(((KitBoss)this).Fighting && !m_ended && ((Head != null && Head.OpeningLive) || AnyPinPartOut()));
			}
			foreach (CapstanStation capstan in m_capstans)
			{
				capstan.Tick(deltaTime);
			}
			if (Overlays != null)
			{
				Overlays.Tick(deltaTime, Deck, flag, m_capstans);
			}
		}

		protected override void KitLateUpdate()
		{
			foreach (exSprite item in m_hiddenArt)
			{
				if ((Object)(object)item != (Object)null && ((Behaviour)item).enabled)
				{
					((Behaviour)item).enabled = false;
				}
			}
			Cleat[] cleats = m_cleats;
			for (int i = 0; i < cleats.Length; i++)
			{
				cleats[i]?.Apply();
			}
			ArmVisual[] arms = m_arms;
			for (int i = 0; i < arms.Length; i++)
			{
				arms[i]?.Apply();
			}
			foreach (CapstanStation capstan in m_capstans)
			{
				capstan.Coil.Apply();
			}
			if (m_lash != null)
			{
				m_lash.Apply();
			}
			if (m_helm != null)
			{
				m_helm.Apply();
			}
			if (Overlays != null)
			{
				Overlays.Apply();
			}
			if (Head != null)
			{
				Head.ApplyVisibility();
			}
		}

		private void FallbackStep(float dt)
		{
			Head.SetRide(ride: false);
			if (Head.State != HeadState.Down)
			{
				m_fallbackTimer = 0f;
				return;
			}
			m_fallbackTimer += dt;
			if (m_fallbackTimer >= 2f)
			{
				m_fallbackTimer = 0f;
				Head.OnRailUnder((HeroLocal.x >= 0f) ? 1 : (-1), HeroLocal.y);
			}
		}

		private void UpdateHero()
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			Player val = Util.Hero();
			m_heroAlive = (Object)(object)val != (Object)null && (Object)(object)val.GetHealthComponent() != (Object)null && val.GetHealthComponent().IsAlive();
			if (!((Object)(object)val == (Object)null))
			{
				HeroLocal = ((KitBoss)this).RoomLocal(((Component)val).transform.position);
				if (HeroLocal.x > 8f)
				{
					HeroSide = 1;
				}
				else if (HeroLocal.x < -8f)
				{
					HeroSide = -1;
				}
			}
		}

		private void OnArmChanged(ArmState a)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			if (a.Phase == ArmPhase.Taut && a.Cleat >= 0)
			{
				KitFx.SpawnFx(Templates.Splash, Vector2.op_Implicit(((KitBoss)this).World(new Vector2(91f * (float)Board[a.Cleat].Side, Layout.Cleats[a.Cleat].y))), 0f);
			}
			ArmVisual armVisual = ((a.Id >= 0 && a.Id < m_arms.Length) ? m_arms[a.Id] : null);
			if (armVisual != null)
			{
				if (a.Phase == ArmPhase.Rise && a.Cleat >= 0)
				{
					armVisual.PlaceAtCleat(a.Cleat);
				}
				armVisual.Show(a.Phase);
				if (a.Phase == ArmPhase.Hold && a.Cleat >= 0)
				{
					KitSelfTest.Note("coil fast on cleat " + a.Cleat + " (L " + Deck.L.ToString("0.00") + ")");
				}
			}
		}

		private void OnHeaveStarted(ArmState a)
		{
			KitSelfTest.Note("heave pulls on cleat " + a.Cleat + " (L " + Deck.L.ToString("0.00") + ")");
		}

		private void OnRailUnder(int side)
		{
			Util.PlaySound(SoundSet.RailUnder, ((Component)this).transform);
			KitSelfTest.Note("rail under: " + ((side > 0) ? "starboard" : "port"));
			if (Head != null && ((KitBoss)this).Fighting && !m_beat && !m_ended && !m_fallback)
			{
				Head.OnRailUnder(side, HeroLocal.y);
			}
		}

		private void OnBlow(Cleat cleat)
		{
			if (PinsLive && !PinCovered(cleat.Index))
			{
				CleatState state = cleat.State;
				state.Blows++;
				state.LastBlow = m_time;
				KitSelfTest.Note("pin blow " + state.Blows + " on cleat " + state.Index + (cleat.Green ? " (green)" : " (iron)"));
				if (state.Blows == 1)
				{
					Util.PlaySound(SoundSet.PinKnock1, ((Component)this).transform);
					return;
				}
				if (state.Blows == 2)
				{
					Util.PlaySound(SoundSet.PinKnock2, ((Component)this).transform);
					return;
				}
				Util.PlaySound(SoundSet.PinKnock3, ((Component)this).transform);
				PinOut(cleat);
			}
		}

		private void PinOut(Cleat cleat)
		{
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			CleatState state = cleat.State;
			int side = state.Side;
			cleat.FlyOut();
			if (state.Holder == Holder.Arm)
			{
				Hold.LetGo(state.Index);
			}
			else if (state.Holder == Holder.Capstan && state.HolderId >= 0 && state.HolderId < m_capstans.Count)
			{
				ReleaseCapstanCoil(m_capstans[state.HolderId]);
			}
			state.Holder = Holder.None;
			state.Blows = 0;
			Deck.Jump(-side);
			LooseBodies(m_scratch);
			HafgufaDrift.Shove(m_scratch, new Vector2((float)(-side), 0f), 90f, 0.3f);
			Util.PlaySound(SoundSet.PinOut, ((Component)this).transform);
			KitSelfTest.Note("pin out on cleat " + state.Index + ": lurch toward " + ((side > 0) ? "port" : "starboard"));
		}

		internal void HardOver(int side)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			Deck.Jump(side);
			Player val = Util.Hero();
			if ((Object)(object)val != (Object)null && IsLoose(val))
			{
				m_scratch.Clear();
				m_scratch.Add(val);
				HafgufaDrift.Shove(m_scratch, new Vector2((float)side, 0f), 110f, 0.4f);
			}
			Util.PlaySound(SoundSet.HardOver, ((Component)this).transform);
			KitSelfTest.Note("hard over " + ((side > 0) ? "starboard" : "port"));
		}

		internal void Belay(CapstanStation cap, int cleat, bool bot)
		{
			CleatState cleatState = Board[cleat];
			if (!cleatState.Awake)
			{
				cap.St.RefundCooldown();
				return;
			}
			int index;
			if (cleatState.Held)
			{
				if (cleatState.Blows > 0)
				{
					index = cap.Index;
					KitSelfTest.Note("capstan " + index + " drove the pin home on cleat " + cleat);
				}
				cleatState.Blows = 0;
				return;
			}
			float num = (float)cleatState.Side * 0.25f;
			if (cap.CoilCleat >= 0)
			{
				num -= (float)Board[cap.CoilCleat].Side * 0.25f;
			}
			if (bot && (!Hold.Allowed(num, 0f) || !Hold.RoomOnRail(cleatState.Side, cap.OwnCoilOn(cleatState.Side) ? 1 : 0)))
			{
				cap.St.RefundCooldown();
				KitSelfTest.Note("bot belay refused: it would drown a rail");
				return;
			}
			if (Hold.IsTargeted(cleat))
			{
				Hold.LetGo(cleat);
				string[] obj = new string[5] { "capstan ", null, null, null, null };
				index = cap.Index;
				obj[1] = index.ToString();
				obj[2] = " took cleat ";
				obj[3] = cleat.ToString();
				obj[4] = " from a kraken arm";
				KitSelfTest.Note(string.Concat(obj));
			}
			ReleaseCapstanCoil(cap);
			cleatState.Holder = Holder.Capstan;
			cleatState.HolderId = cap.Index;
			cleatState.Blows = 0;
			cap.CoilCleat = cleat;
			cap.Coil.PlaceAtCleat(cleat);
			cap.Coil.Show(ArmPhase.Wrap);
			index = cap.Index;
			KitSelfTest.Note("capstan " + index + " belayed cleat " + cleat);
		}

		private void ReleaseCapstanCoil(CapstanStation cap)
		{
			if (cap != null && cap.CoilCleat >= 0)
			{
				CleatState cleatState = Board[cap.CoilCleat];
				if (cleatState.Holder == Holder.Capstan && cleatState.HolderId == cap.Index)
				{
					cleatState.Holder = Holder.None;
					cleatState.Blows = 0;
				}
				cap.CoilCleat = -1;
				cap.Coil.Show(ArmPhase.Whip);
			}
		}

		private int CoilCount()
		{
			int num = 0;
			CleatState[] board = Board;
			for (int i = 0; i < board.Length; i++)
			{
				if (board[i].Held)
				{
					num++;
				}
			}
			return num;
		}

		private bool AnyPinPartOut()
		{
			CleatState[] board = Board;
			foreach (CleatState cleatState in board)
			{
				if (cleatState.Held && cleatState.Blows > 0 && cleatState.Blows < 3)
				{
					return true;
				}
			}
			return false;
		}

		internal bool Braced(Vector2 local)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < Board.Length; i++)
			{
				if (Board[i].Held && Board[i].Awake && Layout.InFoothold(i, local))
				{
					return true;
				}
			}
			return false;
		}

		internal bool HeadSparesTile(int side, int k)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			if (Head == null || !Head.Shown || Head.Side != side)
			{
				return false;
			}
			return Mathf.Abs(-67f + 16f * (float)k + 8f - (Head.Pivot.y + Layout.HeadHitCentre.y)) < 32f;
		}

		internal float DriftSpeedAt(Player p)
		{
			//IL_0019: 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)
			if (!DriftOn || (Object)(object)p == (Object)null || Braced(((KitBoss)this).RoomLocal(((Component)p).transform.position)))
			{
				return 0f;
			}
			return Deck.L * Tuning.DriftMax[Mathf.Clamp(((KitBoss)this).Phase, 1, 3)];
		}

		private bool IsLoose(Player p)
		{
			//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_0051: Invalid comparison between Unknown and I4
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Invalid comparison between Unknown and I4
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Invalid comparison between Unknown and I4
			//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)
			if ((Object)(object)p == (Object)null || (Object)(object)p.GetHealthComponent() == (Object)null || !p.GetHealthComponent().IsAlive())
			{
				return false;
			}
			if (Head != null && (Object)(object)p == (Object)(object)Head.Body.Player)
			{
				return false;
			}
			ePlayerState state = p.GetState();
			if ((int)state == 1 || (int)state == 8 || state - 10 <= 3)
			{
				return false;
			}
			return !Braced(((KitBoss)this).RoomLocal(((Component)p).transform.position));
		}

		internal void LooseBodies(List<Player> into)
		{
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			into.Clear();
			Player val = Util.Hero();
			if (IsLoose(val))
			{
				into.Add(val);
			}
			SystemLevel get = Singleton<SystemLevel>.Get;
			List<GameObject> list = (((Object)(object)get != (Object)null) ? get.GetMonstersSpawned() : null);
			if (list == null)
			{
				return;
			}
			foreach (GameObject item in list)
			{
				if (!((Object)(object)item == (Object)null))
				{
					Player component = item.GetComponent<Player>();
					if ((Object)(object)component != (Object)null && (Object)(object)component != (Object)(object)val && IsLoose(component) && (Object)(object)((KitBoss)this).Arena != (Object)null && KitRoom.Inside(((KitBoss)this).Arena, Vector2.op_Implicit(item.transform.position)))
					{
						into.Add(component);
					}
				}
			}
		}

		private bool SomeoneNear()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			if (Head == null)
			{
				return false;
			}
			Vector2 pivot = Head.Pivot;
			LooseBodies(m_scratch);
			Vector2 val;
			foreach (Player item in m_scratch)
			{
				val = ((KitBoss)this).RoomLocal(((Component)item).transform.position) - pivot;
				if (((Vector2)(ref val)).sqrMagnitude <= 3600f)
				{
					return true;
				}
			}
			Player val2 = Util.Hero();
			if ((Object)(object)val2 != (Object)null && m_heroAlive)
			{
				val = ((KitBoss)this).RoomLocal(((Component)val2).transform.position) - pivot;
				return ((Vector2)(ref val)).sqrMagnitude <= 3600f;
			}
			return false;
		}

		public override bool GetVulnerable()
		{
			if (!((Boss)this).GetAttackable() || Head == null)
			{
				return false;
			}
			if (!Head.EyeOpen && NearestGreenPin() < 0)
			{
				return EscapePin() >= 0;
			}
			return true;
		}

		public override Vector2 GetVulnerableTargetPosition()
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: 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)
			if (Head != null && Head.EyeOpen)
			{
				return Vector2.op_Implicit(((KitBoss)this).World(Head.BotAim)) - WeakpointOffset;
			}
			int num = BotPinTarget();
			if (num >= 0)
			{
				return Vector2.op_Implicit(((KitBoss)this).World(Layout.PinCentre(num))) - WeakpointOffset;
			}
			return HeroFallback();
		}

		private int BotPinTarget()
		{
			if (Head != null && Head.EyeOpen)
			{
				return -1;
			}
			int num = NearestGreenPin();
			if (num < 0)
			{
				return EscapePin();
			}
			return num;
		}

		private int EscapePin()
		{
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			if (!PinsLive || Head == null || Head.Riding || !Deck.AnyUnder || NearestGreenPin() >= 0)
			{
				return -1;
			}
			if (Head.State != HeadState.Down && Head.State != HeadState.Resting && Head.State != HeadState.Dive)
			{
				return -1;
			}
			int num = (Deck.IsUnder(1) ? 1 : (-1));
			int result = -1;
			float num2 = float.MaxValue;
			for (int i = 0; i < Board.Length; i++)
			{
				if (Board[i].Held && Board[i].Awake && Board[i].Side == num)
				{
					Vector2 val = Layout.Cleats[i] - HeroLocal;
					float sqrMagnitude = ((Vector2)(ref val)).sqrMagnitude;
					if (sqrMagnitude < num2)
					{
						num2 = sqrMagnitude;
						result = i;
					}
				}
			}
			return result;
		}

		internal static bool IsBotHero(Player hero)
		{
			if ((Object)(object)hero == (Object)null)
			{
				return false;
			}
			PlayerData playerData = hero.GetPlayerData();
			if (playerData != null)
			{
				return playerData.IsBot;
			}
			return false;
		}

		public override Vector2 GetNonVulnerableTargetPosition()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: 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_008f: 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)
			if (Head != null && Head.State == HeadState.Up)
			{
				return Vector2.op_Implicit(((KitBoss)this).World(Head.BotAim));
			}
			int num = -1;
			float num2 = float.MaxValue;
			int num3 = ((!(Deck.L > 0f)) ? 1 : (-1));
			for (int i = 0; i < Board.Length; i++)
			{
				if (Board[i].Held && Board[i].Awake && Board[i].Side == num3)
				{
					Vector2 val = Layout.Cleats[i] - HeroLocal;

plugins/CrawlCustomBosses/WizardBoss.dll

Decompiled 4 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text.RegularExpressions;
using BepInEx;
using BossKit;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("WizardBoss")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("WizardBoss")]
[assembly: AssemblyTitle("WizardBoss")]
[assembly: AssemblyVersion("1.0.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 WizardBoss
{
	internal static class Blink
	{
		private const int Mask = 21070336;

		public static bool Clear(VaelBoss boss, Vector2 local)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: 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)
			KitBody lifeBody = ((KitBoss)boss).LifeBody;
			Vector3 val = ((KitBoss)boss).World(local);
			for (int i = -1; i <= 1; i += 2)
			{
				Collider[] array = Physics.OverlapSphere(new Vector3(val.x + (float)i * 2f, val.y + 2.5f, 0f), 5f, 21070336, (QueryTriggerInteraction)1);
				foreach (Collider val2 in array)
				{
					if (!((Object)(object)val2 == (Object)null) && (!((Object)(object)lifeBody != (Object)null) || (!((Object)(object)((Component)val2).transform.root == (Object)(object)((Component)lifeBody).transform) && !((Object)(object)val2.attachedRigidbody == (Object)(object)lifeBody.Body))))
					{
						return false;
					}
				}
			}
			return true;
		}

		public static bool OnFloor(VaelBoss boss, Vector2 local, float margin)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			if (Geo.OnFloor(local, margin))
			{
				return KitRoom.Inside(((KitBoss)boss).Arena, Vector2.op_Implicit(((KitBoss)boss).World(local)));
			}
			return false;
		}

		public static Vector2? CircleLanding(VaelBoss boss, Vector2 centre)
		{
			//IL_0001: 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_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: 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_006b: 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)
			if (Clear(boss, centre) && OnFloor(boss, centre, 6f))
			{
				return centre;
			}
			float[] array = new float[2] { 0.3f, 0.5f };
			foreach (float r in array)
			{
				for (int j = 0; j < 8; j++)
				{
					Vector2 val = Geo.RimPoint(centre, (float)j * 45f, r);
					if (val.y <= 38f && Clear(boss, val) && OnFloor(boss, val, 6f))
					{
						return val;
					}
				}
			}
			return null;
		}

		public static Vector2? DefensiveLanding(VaelBoss boss, Vector2 heroLocal, Random rng)
		{
			//IL_0027: 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_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: 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_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: 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_01ad: 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_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			List<KeyValuePair<float, Vector2>> list = new List<KeyValuePair<float, Vector2>>();
			Vector2 val = default(Vector2);
			for (float num = -138f; num <= 140f; num += 6f)
			{
				for (float num2 = -66f; num2 <= 30f; num2 += 6f)
				{
					((Vector2)(ref val))..ctor(num, num2);
					Vector2 val2 = val - heroLocal;
					float magnitude = ((Vector2)(ref val2)).magnitude;
					if (magnitude < 70f || magnitude > 110f)
					{
						continue;
					}
					bool flag = false;
					Vector2[] circles = Geo.Circles;
					foreach (Vector2 centre in circles)
					{
						val2 = Geo.ToCircle(val, centre);
						if (((Vector2)(ref val2)).magnitude <= 1.15f)
						{
							flag = true;
							break;
						}
					}
					if (!flag && Geo.OnFloor(val, 14f))
					{
						list.Add(new KeyValuePair<float, Vector2>(Geo.EdgeDistance(val), val));
					}
				}
			}
			list.Sort((KeyValuePair<float, Vector2> a, KeyValuePair<float, Vector2> b) => b.Key.CompareTo(a.Key));
			int num3 = Mathf.Max(1, list.Count / 3);
			List<Vector2> list2 = new List<Vector2>();
			foreach (KeyValuePair<float, Vector2> item in list)
			{
				if (list2.Count >= num3)
				{
					break;
				}
				if (KitRoom.Inside(((KitBoss)boss).Arena, Vector2.op_Implicit(((KitBoss)boss).World(item.Value))) && Clear(boss, item.Value))
				{
					list2.Add(item.Value);
				}
			}
			if (list2.Count == 0)
			{
				return null;
			}
			return list2[rng.Next(list2.Count)];
		}

		public unsafe static bool Teleport(VaelBoss boss, Vector2 local)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: 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_006e: 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_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: 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)
			KitBody lifeBody = ((KitBoss)boss).LifeBody;
			if ((Object)(object)lifeBody == (Object)null || !lifeBody.Alive)
			{
				return false;
			}
			Vector3 val = ((KitBoss)boss).World(local);
			if (!KitRoom.Inside(((KitBoss)boss).Arena, Vector2.op_Implicit(val)))
			{
				KitLog log = Kit.Log;
				Vector2 val2 = local;
				log.WarnOnce("vael teleport outside", "Vael: a teleport target " + ((object)(*(Vector2*)(&val2))/*cast due to .constrained prefix*/).ToString() + " is outside the room; skipped");
				return false;
			}
			Transform transform = ((Component)lifeBody).transform;
			Vector3 position = default(Vector3);
			((Vector3)(ref position))..ctor(val.x, val.y, transform.position.z);
			transform.position = position;
			if ((Object)(object)lifeBody.Body != (Object)null)
			{
				lifeBody.Body.position = position;
				lifeBody.Body.velocity = Vector3.zero;
			}
			lifeBody.Movement.Stop();
			return true;
		}

		public static void Smoke(VaelBoss boss, Vector2 local)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Templates.Smoke != (Object)null)
			{
				KitFx.SpawnFx(Templates.Smoke, Vector2.op_Implicit(((KitBoss)boss).World(local) + new Vector3(0f, 10f, 0f)), 0f);
			}
		}
	}
	public sealed class VaelBoss : KitBoss
	{
		internal enum S
		{
			Intro,
			Kite,
			Bolt,
			Kindled,
			BlinkToCircle,
			Channel,
			Release,
			Stunned,
			Recover,
			DefensiveBlink,
			Recite,
			Gloat,
			Dying,
			Frozen
		}

		[CompilerGenerated]
		private static class <>O
		{
			public static HitFilter <0>__StaticFilter;
		}

		private S m_state;

		private float m_t;

		private int m_steps;

		private int m_appliedPhase = 1;

		private int m_pendingPhase = 1;

		private float m_castCooldownUntil = float.MaxValue;

		private float m_boltReady;

		private float m_blinkReady;

		private float m_windowTime;

		private float m_nearSince = -1f;

		private float m_allBrokenTime;

		private bool m_noLandingLogged;

		private int m_castCircle = -1;

		private KitStation m_kindleStation;

		private Vector2? m_landing;

		private float m_castLength;

		private int m_nextDir = 1;

		private float m_pulseAt = -1f;

		private bool m_pulseBurst;

		private float m_chevronFlashUntil = -1f;

		private AudioSource m_chant;

		private AudioClip m_chantClip;

		private int m_breakCount;

		private int m_steps2Log;

		private int m_boltsSkipped;

		private Vector2 m_blinkTarget;

		private bool m_reciteChangesPhase;

		private float m_nextSteer;

		private Vector2 m_moveDir;

		private float m_moveRatio;

		private Vector2 m_lastDir = Vector2.zero;

		private bool m_blinkFailed;

		private int m_breakShatterCircle = -1;

		internal static VaelBoss Current;

		internal RuneCircle[] Circles = new RuneCircle[0];

		internal readonly Ratchet Breach = new Ratchet();

		private CircleFx m_fx;

		private Ward m_ward;

		private Spells m_spells;

		private VaelStations m_st;

		private readonly Random m_rng = new Random();

		private float m_lastHurt = -10f;

		private Health m_filteredHealth;

		private int m_botSense;

		private float m_botSenseNotch = float.NaN;

		private int Pi => Mathf.Clamp(m_appliedPhase, 1, 3) - 1;

		private float Now => ((KitBoss)this).UnpausedTime;

		protected override Vector2 BarLocal => Geo.BarLocal;

		internal bool InChannel
		{
			get
			{
				if (m_state == S.Channel)
				{
					return m_castCircle >= 0;
				}
				return false;
			}
		}

		internal int CastCircle => m_castCircle;

		internal float ChannelTimeLeft
		{
			get
			{
				if (!InChannel)
				{
					return 0f;
				}
				return Mathf.Max(0f, m_castLength - m_t);
			}
		}

		internal bool CastCommitted
		{
			get
			{
				if (m_castCircle >= 0)
				{
					if (m_state != S.Kindled && m_state != S.BlinkToCircle)
					{
						return m_state == S.Channel;
					}
					return true;
				}
				return false;
			}
		}

		internal Vector2 CastCentre
		{
			get
			{
				//IL_001a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0009: Unknown result type (might be due to invalid IL or missing references)
				if (m_castCircle < 0)
				{
					return Geo.BossStart;
				}
				return Geo.Circles[m_castCircle];
			}
		}

		internal bool KindleWindowOpen => KindleWindow(heldThroughBlink: false);

		internal bool KindleWindowHeld => KindleWindow(heldThroughBlink: true);

		internal bool DefensiveBlinking => m_state == S.DefensiveBlink;

		private Vector2 VaelLocal
		{
			get
			{
				//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_0010: Unknown result type (might be due to invalid IL or missing references)
				KitBody lifeBody = ((KitBoss)this).LifeBody;
				if (!((Object)(object)lifeBody != (Object)null))
				{
					return Geo.BossStart;
				}
				return ((KitBoss)this).RoomLocal(((Component)lifeBody).transform.position);
			}
		}

		private void Enter(S s)
		{
			m_state = s;
			m_t = 0f;
			m_steps = 0;
			if (s != S.Kite && s != S.Bolt)
			{
				m_nearSince = -1f;
			}
		}

		private bool Step(int bit)
		{
			int num = 1 << bit;
			if ((m_steps & num) != 0)
			{
				return false;
			}
			m_steps |= num;
			return true;
		}

		private void Tick(float dt)
		{
			m_t += dt;
			KitBody lifeBody = ((KitBoss)this).LifeBody;
			if (m_state == S.Dying)
			{
				TickDying();
			}
			else
			{
				if ((Object)(object)lifeBody == (Object)null || !lifeBody.Alive || m_state == S.Intro || m_state == S.Frozen || ((KitBoss)this).Killed)
				{
					return;
				}
				if (m_state == S.Gloat)
				{
					lifeBody.Brain.Stop();
					if (m_t >= 1.6f && Step(0))
					{
						EndCut();
					}
					return;
				}
				if (m_pendingPhase > m_appliedPhase && m_state != S.Recite)
				{
					StartRecite(phaseChange: true);
					return;
				}
				if ((m_state == S.Kite || m_state == S.Bolt || m_state == S.DefensiveBlink) && Now >= m_castCooldownUntil)
				{
					m_windowTime += dt;
				}
				if ((m_state == S.Kite || m_state == S.Bolt) && KindleWindowOpen && m_st != null && m_st.TryTakeKindle(out var circle, out var station, out var who))
				{
					StartKindle(circle, who, station);
					return;
				}
				switch (m_state)
				{
				case S.Kite:
					TickKite(dt);
					break;
				case S.Bolt:
					TickBolt();
					break;
				case S.Kindled:
					TickKindled();
					break;
				case S.BlinkToCircle:
					TickBlinkToCircle();
					break;
				case S.Channel:
					TickChannel(dt);
					break;
				case S.Release:
					TickRelease();
					break;
				case S.Stunned:
					TickStunned();
					break;
				case S.Recover:
					TickRecover();
					break;
				case S.DefensiveBlink:
					TickDefensiveBlink();
					break;
				case S.Recite:
					TickRecite();
					break;
				}
			}
		}

		private void EnterKite()
		{
			Enter(S.Kite);
			m_nextSteer = 0f;
			KitBody lifeBody = ((KitBoss)this).LifeBody;
			if ((Object)(object)lifeBody != (Object)null)
			{
				lifeBody.Brain.Stop();
			}
		}

		private void TickKite(float dt)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Invalid comparison between Unknown and I4
			//IL_0070: 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_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: 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_008b: 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_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Invalid comparison between Unknown and I4
			//IL_00d5: 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_0061: Invalid comparison between Unknown and I4
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Invalid comparison between Unknown and I4
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: 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_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			KitBody lifeBody = ((KitBoss)this).LifeBody;
			Player val = Util.Hero();
			if ((Object)(object)val == (Object)null || (Object)(object)val.GetHealthComponent() == (Object)null || !val.GetHealthComponent().IsAlive())
			{
				lifeBody.Brain.Stop();
				return;
			}
			ePlayerState state = lifeBody.Player.GetState();
			if ((int)state != 2 && (int)state != 3)
			{
				if (m_t > 1f && ((int)state == 13 || (int)state == 15))
				{
					lifeBody.EndAction();
				}
				return;
			}
			Vector2 vaelLocal = VaelLocal;
			Vector2 val2 = ((KitBoss)this).RoomLocal(((Component)val).transform.position);
			Vector2 val3 = val2 - vaelLocal;
			float magnitude = ((Vector2)(ref val3)).magnitude;
			if (AllBroken())
			{
				m_allBrokenTime += dt;
				if (m_allBrokenTime >= 6f)
				{
					StartRecite(phaseChange: false);
					return;
				}
			}
			else
			{
				m_allBrokenTime = 0f;
			}
			if (CheckDefensiveBlink(magnitude, val2))
			{
				return;
			}
			if (KindleWindowOpen && m_windowTime >= Tuning.SelfLight[Pi])
			{
				int num = -1;
				float num2 = float.MaxValue;
				for (int i = 0; i < Circles.Length; i++)
				{
					if (Circles[i].State == CircleState.Dark)
					{
						val3 = Geo.Circles[i] - vaelLocal;
						float magnitude2 = ((Vector2)(ref val3)).magnitude;
						if (magnitude2 < num2)
						{
							num2 = magnitude2;
							num = i;
						}
					}
				}
				if (num >= 0)
				{
					StartKindle(num, "self", null);
					return;
				}
			}
			if (Now >= m_boltReady && magnitude <= 180f && BoltSpawn(vaelLocal, (val2.x < vaelLocal.x) ? (-1f) : 1f, val2 + new Vector2(0f, 8f)).HasValue)
			{
				StartBolt(val);
			}
			else
			{
				Steer(vaelLocal, val2);
			}
		}

		private bool AllBroken()
		{
			RuneCircle[] circles = Circles;
			for (int i = 0; i < circles.Length; i++)
			{
				if (!circles[i].Broken)
				{
					return false;
				}
			}
			return Circles.Length != 0;
		}

		private void Steer(Vector2 me, Vector2 h)
		{
			//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_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_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: 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_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: 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_0094: 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_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: 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_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: 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_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			KitBody lifeBody = ((KitBoss)this).LifeBody;
			if (Now >= m_nextSteer)
			{
				m_nextSteer = Now + 0.2f;
				Vector2 val = h - me;
				float magnitude = ((Vector2)(ref val)).magnitude;
				m_moveRatio = 0f;
				if (magnitude < 60f || magnitude > 110f)
				{
					float num = float.MinValue;
					Vector2 val2 = Vector2.zero;
					Vector2 val3 = default(Vector2);
					for (int i = 0; i < 16; i++)
					{
						float num2 = (float)i * 22.5f * ((float)Math.PI / 180f);
						((Vector2)(ref val3))..ctor(Mathf.Cos(num2), Mathf.Sin(num2));
						Vector2 val4 = me + val3 * 20f;
						if (Geo.OnFloor(val4, 14f) && !(val4.y > 36f) && !PathHitsBlocker(me, val3))
						{
							val = val4 - h;
							float num3 = 0f - Mathf.Abs(((Vector2)(ref val)).magnitude - 85f) + 4f * Vector2.Dot(val3, m_lastDir);
							if (num3 > num)
							{
								num = num3;
								val2 = val3;
							}
						}
					}
					if (val2 != Vector2.zero)
					{
						m_moveDir = val2;
						m_moveRatio = 0.45f;
						m_lastDir = val2;
					}
				}
			}
			if (m_moveRatio > 0f && Geo.OnFloor(me + m_moveDir * 4f, 7f) && !Geo.CapsuleInBlocker(me + m_moveDir * 2f, 0f))
			{
				lifeBody.Brain.SetMove(m_moveDir, m_moveRatio);
				return;
			}
			m_moveRatio = 0f;
			lifeBody.Brain.Face(h - me);
		}

		private static bool PathHitsBlocker(Vector2 me, Vector2 dir)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			for (float num = 2f; num <= 20.01f; num += 2f)
			{
				if (Geo.CapsuleInBlocker(me + dir * num, 0f))
				{
					return true;
				}
			}
			return false;
		}

		private float FacingSign()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			KitBody lifeBody = ((KitBoss)this).LifeBody;
			if (!((Object)(object)lifeBody != (Object)null) || !(((Component)lifeBody).transform.localScale.x < 0f))
			{
				return 1f;
			}
			return -1f;
		}

		private Vector2? BoltSpawn(Vector2 rootLocal, float sx, Vector2 targetLocal)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: 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_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: 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_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: 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_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: 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_0098: 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_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: 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)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Vector3 val = ((KitBoss)this).World(rootLocal + new Vector2(0f, 7f));
				Vector3 val2 = ((KitBoss)this).World(targetLocal);
				int num = Mathf.Min(Tuning.BoltNodeX.Length, Tuning.BoltNodeY.Length);
				for (int i = 0; i < num; i++)
				{
					Vector2 val3 = rootLocal + new Vector2(Tuning.BoltNodeX[i] * sx, Tuning.BoltNodeY[i]);
					Vector3 val4 = ((KitBoss)this).World(val3);
					if (!Physics.CheckSphere(new Vector3(val4.x, val4.y, 0f), 2f, 16777728, (QueryTriggerInteraction)1) && KitGeom.LineClear(Vector2.op_Implicit(val), Vector2.op_Implicit(val4), 16777728) && KitGeom.LineClear(Vector2.op_Implicit(val4), Vector2.op_Implicit(val2), 16777728))
					{
						return val3;
					}
				}
			}
			catch (Exception ex)
			{
				Kit.Log.WarnOnce("vael bolt spawn", ex);
			}
			return null;
		}

		private void StartBolt(Player hero)
		{
			//IL_001e: 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_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			KitBody lifeBody = ((KitBoss)this).LifeBody;
			lifeBody.Brain.Stop();
			lifeBody.Brain.Face(((KitBoss)this).RoomLocal(((Component)hero).transform.position) - VaelLocal);
			lifeBody.PlayStatus(Templates.Bolt);
			m_boltReady = Now + Tuning.BoltCooldown[Pi];
			Enter(S.Bolt);
		}

		private void TickBolt()
		{
			//IL_001e: 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_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Invalid comparison between Unknown and I4
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Invalid comparison between Unknown and I4
			//IL_0083: 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_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: 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_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			KitBody lifeBody = ((KitBoss)this).LifeBody;
			Player val = Util.Hero();
			if ((Object)(object)val != (Object)null)
			{
				Vector2 val2 = ((KitBoss)this).RoomLocal(((Component)val).transform.position) - VaelLocal;
				if (CheckDefensiveBlink(((Vector2)(ref val2)).magnitude, ((KitBoss)this).RoomLocal(((Component)val).transform.position)))
				{
					return;
				}
			}
			if (m_t >= 0.4f && Step(0) && (Object)(object)val != (Object)null)
			{
				Vector2 val3 = ((KitBoss)this).RoomLocal(((Component)val).transform.position) + new Vector2(0f, 8f);
				Vector2? val4 = BoltSpawn(VaelLocal, FacingSign(), val3);
				if (val4.HasValue)
				{
					Vector2 val5 = val3 - val4.Value;
					float num = Mathf.Atan2(val5.y, val5.x) * 57.29578f;
					for (int i = -1; i <= 1; i++)
					{
						KitFx.SpawnOwned(Templates.BoltFx, Vector2.op_Implicit(((KitBoss)this).World(val4.Value)), num + (float)i * 15f, ((Component)lifeBody).gameObject, true);
					}
				}
				else if (++m_boltsSkipped <= 5)
				{
					KitSelfTest.Note("bolt fan skipped (no clear start)");
				}
			}
			if (m_t >= 0.7f || (int)lifeBody.Player.GetState() != 15)
			{
				if ((int)lifeBody.Player.GetState() == 15)
				{
					lifeBody.EndAction();
				}
				EnterKite();
			}
		}

		private unsafe bool CheckDefensiveBlink(float dist, Vector2 heroLocal)
		{
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Invalid comparison between Unknown and I4
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: 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_0089: Unknown result type (might be due to invalid IL or missing references)
			if (dist > 28f)
			{
				m_nearSince = -1f;
				return false;
			}
			if (m_nearSince < 0f)
			{
				m_nearSince = Now;
			}
			if (Now - m_nearSince < 0.4f || Now < m_blinkReady)
			{
				return false;
			}
			Vector2? val = Blink.DefensiveLanding(this, heroLocal, m_rng);
			if (!val.HasValue)
			{
				if (!m_noLandingLogged)
				{
					m_noLandingLogged = true;
					KitLog log = ((KitBoss)this).Ctx.Log;
					Vector2 val2 = heroLocal;
					log.Warn("Vael: no defensive blink landing from hero " + ((object)(*(Vector2*)(&val2))/*cast due to .constrained prefix*/).ToString() + " (logged once)");
				}
				m_blinkReady = Now + 1f;
				return false;
			}
			KitBody lifeBody = ((KitBoss)this).LifeBody;
			if ((int)lifeBody.Player.GetState() == 15)
			{
				lifeBody.EndAction();
			}
			lifeBody.Brain.Stop();
			m_blinkTarget = val.Value;
			m_blinkReady = Now + Tuning.BlinkCooldown[Pi];
			m_nearSince = -1f;
			m_fx.ShowLanding(m_blinkTarget, Now, 0.7f);
			Enter(S.DefensiveBlink);
			KitSelfTest.Note("blink (defensive)");
			return true;
		}

		private bool BlinkTimeline(Func<Vector2?> landingAt)
		{
			//IL_0041: 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_0084: Unknown result type (might be due to invalid IL or missing references)
			KitBody lifeBody = ((KitBoss)this).LifeBody;
			if (Step(10))
			{
				lifeBody.Brain.Stop();
				Cut(Templates.BlinkOut, collisionOff: true);
			}
			if (m_t >= 0.07f && Step(11))
			{
				Blink.Smoke(this, VaelLocal);
			}
			if (m_t >= 0.35f && Step(12))
			{
				Vector2? val = landingAt();
				if (val.HasValue && Blink.Teleport(this, val.Value))
				{
					Blink.Smoke(this, val.Value);
				}
				else
				{
					m_blinkFailed = true;
				}
				Cut(Templates.BlinkIn);
			}
			if (m_t >= 0.7f)
			{
				return Step(13);
			}
			return false;
		}

		private void TickDefensiveBlink()
		{
			if (m_t <= 0f || m_steps == 0)
			{
				m_blinkFailed = false;
			}
			if (BlinkTimeline(() => (!Blink.Clear(this, m_blinkTarget)) ? ((Vector2?)null) : new Vector2?(m_blinkTarget)))
			{
				EndCut();
				EnterKite();
			}
		}

		internal void StartKindle(int circle, string who, KitStation station)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Invalid comparison between Unknown and I4
			if (!KindleWindowOpen || circle < 0 || circle >= Circles.Length || Circles[circle].State != CircleState.Dark)
			{
				if ((Object)(object)station != (Object)null)
				{
					station.RefundCooldown();
				}
				return;
			}
			KitBody lifeBody = ((KitBoss)this).LifeBody;
			if ((int)lifeBody.Player.GetState() == 15)
			{
				lifeBody.EndAction();
			}
			lifeBody.Brain.Stop();
			m_castCircle = circle;
			m_kindleStation = station;
			m_landing = null;
			m_windowTime = 0f;
			m_st.ResetCast();
			Circles[circle].SetState(CircleState.Kindling);
			VaelCues.Play(VaelCues.Kindle, ((Object)(object)m_st.Braziers[circle] != (Object)null) ? ((Component)m_st.Braziers[circle]).transform : ((Component)this).transform);
			Enter(S.Kindled);
			KitSelfTest.Note("kindle " + Geo.CircleNames[circle] + " (" + who + ")");
		}

		private void TickKindled()
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			KitBody lifeBody = ((KitBoss)this).LifeBody;
			lifeBody.Brain.Stop();
			Player val = Util.Hero();
			if ((Object)(object)val != (Object)null)
			{
				lifeBody.Brain.Face(((KitBoss)this).RoomLocal(((Component)val).transform.position) - VaelLocal);
			}
			if (m_t >= 0.3f && Step(0))
			{
				m_landing = Blink.CircleLanding(this, CastCentre);
				if (m_landing.HasValue)
				{
					m_fx.ShowLanding(m_landing.Value, Now, 1.4f);
				}
			}
			if (m_t < 1f)
			{
				return;
			}
			if (!m_landing.HasValue || !Blink.Clear(this, m_landing.Value))
			{
				int num = (int)((m_t - 1f) / 0.25f);
				if (num + 20 < 31 && Step(num + 20))
				{
					m_landing = Blink.CircleLanding(this, CastCentre);
					if (m_landing.HasValue)
					{
						m_fx.ShowLanding(m_landing.Value, Now, 0.7f);
					}
				}
				if (!m_landing.HasValue)
				{
					if (m_t >= 2.5f)
					{
						DropKindle("no clear landing");
					}
					return;
				}
			}
			m_blinkFailed = false;
			Enter(S.BlinkToCircle);
		}

		private void DropKindle(string why)
		{
			if ((Object)(object)m_kindleStation != (Object)null)
			{
				m_kindleStation.RefundCooldown();
			}
			CancelCast(refund: true);
			((KitBoss)this).Ctx.Log.Info("Vael: kindle dropped (" + why + ")");
			EnterKite();
		}

		private void TickBlinkToCircle()
		{
			bool flag = BlinkTimeline(delegate
			{
				//IL_002a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				if (m_landing.HasValue && Blink.Clear(this, m_landing.Value))
				{
					return m_landing;
				}
				m_landing = Blink.CircleLanding(this, CastCentre);
				return m_landing;
			});
			if (m_blinkFailed && m_t >= 0.35f)
			{
				if (flag || m_t >= 0.7f)
				{
					EndCut();
					DropKindle("landing blocked at the teleport");
				}
			}
			else if (flag)
			{
				StartChannel();
			}
		}

		private void StartChannel()
		{
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			KitBody lifeBody = ((KitBoss)this).LifeBody;
			int castCircle = m_castCircle;
			lifeBody.Player.StartCutscene(Templates.Channel, false, 0f);
			lifeBody.Health.StopInvincibility("cut");
			lifeBody.Brain.Stop();
			Enter(S.Channel);
			m_ward.ResetCast();
			m_pulseAt = -1f;
			m_pulseBurst = false;
			m_botSense = 0;
			m_botSenseNotch = float.NaN;
			PlayerData orreryRider = m_st.OrreryRider;
			int nextDir = m_nextDir;
			m_nextDir = -m_nextDir;
			Breach.Start(m_rng.Next(12), nextDir, orreryRider != null, Pi);
			Circles[castCircle].SetState(CircleState.Lit);
			m_fx.RimOn = true;
			m_fx.CircleLocal = Geo.Circles[castCircle];
			m_fx.SparksOn = true;
			m_fx.SparkFraction = 0f;
			m_fx.LandingUntil = -1f;
			m_castLength = Tuning.CastTime[Pi];
			m_chant = VaelCues.Play(VaelCues.Chant(m_appliedPhase), ((Component)lifeBody).transform);
			m_chantClip = (((Object)(object)m_chant != (Object)null) ? m_chant.clip : null);
			m_spells.Begin(m_appliedPhase);
			KitSelfTest.Note("channel " + Geo.CircleNames[castCircle] + ((orreryRider != null) ? " (manned)" : " (empty)"));
		}

		private void TickChannel(float dt)
		{
			//IL_0032: 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_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			KitBody lifeBody = ((KitBoss)this).LifeBody;
			if (m_ward.RingOut)
			{
				StartBacklash();
				return;
			}
			PlayerData orreryRider = m_st.OrreryRider;
			Vector2 val = ((orreryRider != null) ? orreryRider.GetInputMove() : Vector2.zero);
			Breach.Tick(dt, orreryRider != null, val.x, val.y);
			if (Breach.BeatThisTick)
			{
				m_chevronFlashUntil = Now + 0.1f;
				VaelCues.Play(VaelCues.Tick, ((Object)(object)m_st.Orrery != (Object)null) ? ((Component)m_st.Orrery).transform : ((Component)lifeBody).transform);
			}
			if (Breach.StepThisTick)
			{
				VaelCues.Play(VaelCues.Step, ((Object)(object)m_st.Orrery != (Object)null) ? ((Component)m_st.Orrery).transform : ((Component)lifeBody).transform);
				if (++m_steps2Log <= 60)
				{
					KitSelfTest.Note("ratchet step");
				}
			}
			m_fx.SparkFraction = ((m_castLength > 0f) ? (m_t / m_castLength) : 1f);
			m_spells.Tick(dt, m_t, m_castLength);
			if (m_pulseAt < 0f && m_castLength - m_t >= 0.5f && m_st.TryTakePulse(m_castCircle))
			{
				m_pulseAt = m_t;
				VaelCues.Play(VaelCues.WardPulse, ((Component)lifeBody).transform);
				KitSelfTest.Note("pulse");
			}
			if (m_pulseAt >= 0f && !m_pulseBurst && m_t - m_pulseAt >= 0.5f)
			{
				m_pulseBurst = true;
				KitFx.SpawnOwned(Templates.PulseFx, Vector2.op_Implicit(((KitBoss)this).World(CastCentre)), 0f, ((Component)lifeBody).gameObject, true);
				m_ward.GlideLeft = 0.3f;
			}
			if (m_t >= m_castLength)
			{
				StartRelease();
			}
		}

		private void StartRelease()
		{
			m_spells.End();
			Cut(Templates.Release);
			Enter(S.Release);
		}

		private void TickRelease()
		{
			//IL_0024: 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_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_0036: Unknown result type (might be due to invalid IL or missing references)
			KitBody lifeBody = ((KitBoss)this).LifeBody;
			if (m_t >= 0.3f && Step(0))
			{
				Vector2 castCentre = CastCentre;
				KitFx.SpawnOwned(Templates.NovaFx, Vector2.op_Implicit(((KitBoss)this).World(castCentre)), 0f, ((Component)lifeBody).gameObject, true);
				m_spells.End();
				m_fx.SparksOn = false;
				m_fx.RimOn = false;
				Breach.Stop();
				if (m_castCircle >= 0)
				{
					Circles[m_castCircle].SetState(CircleState.Dark);
				}
				m_castCircle = -1;
				m_st.ResetCast();
				KitSelfTest.Note("release");
			}
			if (m_t >= 0.6f)
			{
				EndCut();
				m_castCooldownUntil = Now + Tuning.CastCooldown[Pi];
				EnterKite();
			}
		}

		private void StartBacklash()
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			KitBody lifeBody = ((KitBoss)this).LifeBody;
			int castCircle = m_castCircle;
			Vector2 castCentre = CastCentre;
			Vector2 ringOutDir = m_ward.RingOutDir;
			m_ward.RingOut = false;
			ApplyBacklashDamage();
			StopChant();
			m_spells.End();
			m_fx.SparksOn = false;
			m_fx.RimOn = false;
			Breach.Stop();
			if (castCircle >= 0)
			{
				Circles[castCircle].SetState(CircleState.Shatter);
				Circles[castCircle].BrokenOrder = m_breakCount++;
			}
			m_fx.Backlash(castCentre, Now);
			m_st.SetOrreryDark(dark: true);
			m_st.ResetCast();
			m_castCircle = -1;
			m_breakShatterCircle = castCircle;
			float num = SafeThrow(VaelLocal, ringOutDir, 8f);
			lifeBody.Stun(0.55f + Tuning.StunTime[Pi] + 0.2f, Templates.Backlash);
			lifeBody.HoldVulnerable = true;
			if (num > 0.01f)
			{
				lifeBody.Movement.AddImpulse(ringOutDir * Ward.ImpulseFor(num, Ward.DecayK(lifeBody.Movement), Time.fixedDeltaTime));
			}
			Enter(S.Stunned);
			KitSelfTest.Note("Backlash");
		}

		private void ApplyBacklashDamage()
		{
			try
			{
				Health lifeHealth = ((KitBoss)this).LifeHealth;
				if ((Object)(object)lifeHealth == (Object)null)
				{
					return;
				}
				float healthCurrent = lifeHealth.GetHealthCurrent();
				float healthMax = lifeHealth.GetHealthMax();
				float num = 0f;
				float[] phaseThresholds = ((KitBoss)this).PhaseThresholds;
				for (int i = 0; i < phaseThresholds.Length; i++)
				{
					float num2 = phaseThresholds[i] * healthMax;
					if (num2 < healthCurrent && num2 > num)
					{
						num = num2;
					}
				}
				float num3 = Mathf.Min(2f, healthCurrent - (num + 0.25f));
				if (!(num3 <= 0.001f))
				{
					lifeHealth.AnimVulnerableOff();
					float num4 = Util.Get<float>((object)lifeHealth, "m_damageResistanceFinal");
					lifeHealth.DamageNoSource(num3 * Mathf.Max(0.0001f, num4));
				}
			}
			catch (Exception ex)
			{
				Kit.Log.WarnOnce("vael backlash damage", ex);
			}
		}

		private float SafeThrow(Vector2 from, Vector2 dir, float max)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: 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)
			float result = 0f;
			for (float num = 1f; num <= max + 0.01f; num += 1f)
			{
				Vector2 val = from + dir * num;
				if (val.y > 38f || !Blink.OnFloor(this, val, 6f) || !Blink.Clear(this, val))
				{
					break;
				}
				result = num;
			}
			return result;
		}

		private void TickStunned()
		{
			KitBody lifeBody = ((KitBoss)this).LifeBody;
			if (m_breakShatterCircle >= 0 && m_t >= EnvArt.CircleShatter.length && Step(0))
			{
				Circles[m_breakShatterCircle].SetState(CircleState.Broken);
				m_breakShatterCircle = -1;
			}
			if (m_t >= 0.55f && Step(1) && (Object)(object)lifeBody.Anim != (Object)null)
			{
				lifeBody.Anim.Play(Templates.Stunned);
			}
			if (m_t >= 0.55f + Tuning.StunTime[Pi])
			{
				if (m_breakShatterCircle >= 0)
				{
					Circles[m_breakShatterCircle].SetState(CircleState.Broken);
					m_breakShatterCircle = -1;
				}
				lifeBody.HoldVulnerable = false;
				m_st.SetOrreryDark(dark: false);
				Cut(Templates.Recover);
				Enter(S.Recover);
			}
		}

		private void TickRecover()
		{
			if (m_t >= 0.7f)
			{
				EndCut();
				m_castCooldownUntil = Now + Tuning.CastCooldown[Pi];
				EnterKite();
			}
		}

		private void StartRecite(bool phaseChange)
		{
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			KitBody lifeBody = ((KitBoss)this).LifeBody;
			lifeBody.Health.StartInvincibility("recite", 2.6f);
			CancelCast(refund: true);
			lifeBody.HoldVulnerable = false;
			if (m_breakShatterCircle >= 0)
			{
				m_breakShatterCircle = -1;
			}
			m_reciteChangesPhase = phaseChange;
			if (phaseChange)
			{
				m_appliedPhase = Mathf.Clamp(m_pendingPhase, 1, 3);
				RuneCircle[] circles = Circles;
				foreach (RuneCircle runeCircle in circles)
				{
					if (runeCircle.Broken)
					{
						runeCircle.SetState(CircleState.Dark);
						runeCircle.BrokenOrder = -1;
					}
				}
			}
			else
			{
				RuneCircle runeCircle2 = null;
				RuneCircle[] circles = Circles;
				foreach (RuneCircle runeCircle3 in circles)
				{
					if (runeCircle3.Broken && (runeCircle2 == null || runeCircle3.BrokenOrder < runeCircle2.BrokenOrder))
					{
						runeCircle2 = runeCircle3;
					}
				}
				if (runeCircle2 != null)
				{
					runeCircle2.SetState(CircleState.Dark);
					runeCircle2.BrokenOrder = -1;
				}
			}
			m_st.SetOrreryDark(dark: true);
			m_blinkTarget = Geo.BossStart;
			m_blinkFailed = false;
			m_allBrokenTime = 0f;
			Enter(S.Recite);
			KitSelfTest.Note(phaseChange ? ("phase " + m_appliedPhase + " recite") : "short recite");
		}

		private void TickRecite()
		{
			if ((m_steps & 0x2000) != 0 || BlinkTimeline(() => (!Blink.Clear(this, m_blinkTarget)) ? Blink.CircleLanding(this, m_blinkTarget) : new Vector2?(m_blinkTarget)))
			{
				float num = m_t - 0.7f;
				if (Step(1))
				{
					Cut(Templates.Recite);
				}
				if (num >= 0.5333f && Step(2) && m_reciteChangesPhase && m_appliedPhase >= 2)
				{
					m_st.WakeG4();
				}
				if (num >= 1.6f)
				{
					EndCut();
					m_st.SetOrreryDark(dark: false);
					m_castCooldownUntil = Now + Tuning.CastCooldown[Pi];
					m_windowTime = 0f;
					EnterKite();
				}
			}
		}

		private void TickDying()
		{
			int num = Mathf.Min(Circles.Length, (int)(m_t / 0.15f) + 1);
			for (int i = 0; i < num; i++)
			{
				if (Step(i))
				{
					Circles[i].SetState(CircleState.Dark);
				}
			}
		}

		private void CancelCast(bool refund)
		{
			try
			{
				StopChant();
				if (m_spells != null)
				{
					m_spells.End();
				}
				Breach.Stop();
				if (m_fx != null)
				{
					m_fx.RimOn = false;
					m_fx.SparksOn = false;
					m_fx.LandingUntil = -1f;
				}
				if (m_castCircle >= 0 && m_castCircle < Circles.Length)
				{
					RuneCircle runeCircle = Circles[m_castCircle];
					if (runeCircle.State == CircleState.Kindling || runeCircle.State == CircleState.Lit)
					{
						runeCircle.SetState(CircleState.Dark);
					}
				}
				m_castCircle = -1;
				if (m_st != null)
				{
					if (refund)
					{
						m_st.ResetCast();
					}
					else
					{
						m_st.PulseUsed = false;
					}
					m_st.ClearClaim();
				}
				if (m_ward != null)
				{
					m_ward.ResetCast();
				}
				m_pulseAt = -1f;
				m_pulseBurst = false;
			}
			catch (Exception ex)
			{
				Kit.Log.WarnOnce("vael cancel cast", ex);
			}
		}

		private void StopChant()
		{
			try
			{
				if ((Object)(object)m_chant != (Object)null && (Object)(object)m_chantClip != (Object)null && (Object)(object)m_chant.clip == (Object)(object)m_chantClip && m_chant.isPlaying)
				{
					SystemAudio.Stop(m_chant, 0.08f);
				}
			}
			catch (Exception ex)
			{
				Kit.Log.WarnOnce("vael chant stop", ex);
			}
			m_chant = null;
			m_chantClip = null;
		}

		internal bool HeroDusted()
		{
			if (m_st != null)
			{
				return m_st.HeroDusted;
			}
			return false;
		}

		private bool KindleWindow(bool heldThroughBlink)
		{
			KitBody lifeBody = ((KitBoss)this).LifeBody;
			bool flag = m_state == S.Kite || m_state == S.Bolt || (heldThroughBlink && m_state == S.DefensiveBlink);
			if (((KitBoss)this).Fighting && (Object)(object)lifeBody != (Object)null && lifeBody.Alive && flag && ((KitBoss)this).UnpausedTime >= m_castCooldownUntil && m_pendingPhase <= m_appliedPhase)
			{
				return m_castCircle < 0;
			}
			return false;
		}

		protected override void BuildArena(Room room)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: 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_00ad: Unknown result type (might be due to invalid IL or missing references)
			Current = this;
			m_ward = new Ward(this);
			m_spells = new Spells(this);
			m_st = new VaelStations(this);
			RuneCircle.SetZ(KitArt.CreateSprite(((Component)room).transform, EnvArt.Env, "VaelFloor", 0, ((KitBoss)this).World(Geo.FloorLocal), (Anchor)4, false, 0f), 99.5f);
			RuneCircle.SetZ(KitArt.CreateSprite(((Component)room).transform, EnvArt.Env, "VaelBackWall", 0, ((KitBoss)this).World(Geo.BackWallLocal), (Anchor)4, false, 0f), 99.5f);
			Circles = new RuneCircle[4];
			for (int i = 0; i < 4; i++)
			{
				Circles[i] = new RuneCircle(i, room, Geo.Circles[i]);
			}
			m_fx = new CircleFx(room);
			m_spells.BuildDouble(room);
			m_st.Spawn(room);
		}

		protected override KitBody SpawnBodies(Room room)
		{
			//IL_0048: 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_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Expected O, but got Unknown
			if (m_ward == null)
			{
				m_ward = new Ward(this);
			}
			if (m_spells == null)
			{
				m_spells = new Spells(this);
			}
			if (m_st == null)
			{
				m_st = new VaelStations(this);
			}
			Current = this;
			KitBody val = KitBodies.Spawn<VaelBrain>((KitBoss)(object)this, Templates.Body, Geo.BossStart, "Vael");
			Health health = val.Health;
			object obj = <>O.<0>__StaticFilter;
			if (obj == null)
			{
				HitFilter val2 = StaticFilter;
				<>O.<0>__StaticFilter = val2;
				obj = (object)val2;
			}
			KitHealth.SetFilter(health, (HitFilter)obj);
			m_filteredHealth = val.Health;
			if ((Object)(object)val.Health != (Object)null)
			{
				VaelFilterGuard vaelFilterGuard = ((Component)val.Health).gameObject.GetComponent<VaelFilterGuard>();
				if ((Object)(object)vaelFilterGuard == (Object)null)
				{
					vaelFilterGuard = ((Component)val.Health).gameObject.AddComponent<VaelFilterGuard>();
				}
				vaelFilterGuard.Health = val.Health;
			}
			val.VelocityOverride = m_ward.OnFixedStep;
			val.Damaged += OnVaelDamaged;
			val.KeepInRoom = true;
			val.GuardStuns = true;
			val.RefuseStatuses = true;
			if ((Object)(object)val.Body != (Object)null && val.Body.drag != 0f)
			{
				((KitBoss)this).Ctx.Log.Info("Vael: Rigidbody drag was " + val.Body.drag + ", set to 0 (the shove formula assumes none)");
				val.Body.drag = 0f;
			}
			return val;
		}

		private void OnVaelDamaged(DamageInfo info)
		{
			try
			{
				if (m_state != S.Channel && info != null && !(info.m_amount <= 0f) && !info.m_isDamageFromStatus && KitHealth.IsHeroHit(info) && ((KitBoss)this).UnpausedTime - m_lastHurt >= 0.25f)
				{
					m_lastHurt = ((KitBoss)this).UnpausedTime;
					VaelCues.Play(VaelCues.Hurt, ((Object)(object)((KitBoss)this).LifeBody != (Object)null) ? ((Component)((KitBoss)this).LifeBody).transform : null);
				}
			}
			catch (Exception ex)
			{
				Kit.Log.WarnOnce("vael hurt", ex);
			}
		}

		protected override IEnumerator Intro()
		{
			KitBody lifeBody = ((KitBoss)this).LifeBody;
			if ((Object)(object)lifeBody != (Object)null && lifeBody.Alive)
			{
				lifeBody.Brain.Face(Vector2.down);
				Cut(Templates.Recite);
			}
			for (int i = 0; i < Circles.Length; i++)
			{
				Circles[i].SetState(CircleState.Kindling);
				yield return (object)new WaitForSeconds(0.25f);
			}
			yield return (object)new WaitForSeconds(Mathf.Max(0f, 1.6f - (float)Circles.Length * 0.25f));
			EndCut();
			RuneCircle[] circles = Circles;
			for (int j = 0; j < circles.Length; j++)
			{
				circles[j].SetState(CircleState.Dark);
			}
			yield return (object)new WaitForSeconds(Mathf.Max(0f, 0.29999995f));
		}

		protected override void OnFightStart()
		{
			KitBody lifeBody = ((KitBoss)this).LifeBody;
			m_appliedPhase = 1;
			m_castCooldownUntil = ((KitBoss)this).UnpausedTime + 1.5f;
			m_boltReady = ((KitBoss)this).UnpausedTime + 0.8f;
			m_blinkReady = ((KitBoss)this).UnpausedTime;
			m_nextDir = ((m_rng.Next(2) == 0) ? 1 : (-1));
			EnterKite();
			if ((Object)(object)lifeBody != (Object)null)
			{
				string text = Ward.Ratios(lifeBody.Movement);
				((KitBoss)this).Ctx.Log.Info("Vael: fight start, " + text + " (expected 20 and 20), drag " + (((Object)(object)lifeBody.Body != (Object)null) ? lifeBody.Body.drag : (-1f)));
				KitSelfTest.Note("k ratios " + text);
			}
		}

		protected override void OnPhase(int phase)
		{
			m_pendingPhase = Mathf.Max(m_pendingPhase, phase);
		}

		protected override void OnFrozen(bool frozen)
		{
			KitBody lifeBody = ((KitBoss)this).LifeBody;
			if (frozen)
			{
				if (m_state == S.Dying || m_state == S.Gloat)
				{
					return;
				}
				CancelCast(refund: true);
				if ((Object)(object)lifeBody != (Object)null)
				{
					lifeBody.HoldVulnerable = false;
					lifeBody.Freeze(true);
				}
				if (m_breakShatterCircle >= 0 && m_breakShatterCircle < Circles.Length)
				{
					Circles[m_breakShatterCircle].SetState(CircleState.Broken);
				}
				m_breakShatterCircle = -1;
				if (m_st != null)
				{
					m_st.SetOrreryDark(dark: false);
					if (m_state == S.Recite && m_reciteChangesPhase && m_appliedPhase >= 2)
					{
						m_st.WakeG4();
					}
				}
				Enter(S.Frozen);
			}
			else if (m_state == S.Frozen)
			{
				EndCut();
				Enter(S.Kite);
			}
		}

		protected override void OnHeroKilledKit(Player hero)
		{
			ClearHitFilter();
			if (m_state != S.Dying)
			{
				CancelCast(refund: true);
				KitBody lifeBody = ((KitBoss)this).LifeBody;
				if ((Object)(object)lifeBody != (Object)null)
				{
					lifeBody.HoldVulnerable = false;
					lifeBody.Brain.Stop();
				}
				m_st.SetOrreryDark(dark: false);
				Enter(S.Gloat);
				Cut(Templates.Recite);
			}
		}

		protected override void OnBossDying(DamageInfo info)
		{
			ClearHitFilter();
			try
			{
				CancelCast(refund: false);
			}
			finally
			{
				m_spells.End();
				if (m_fx != null)
				{
					m_fx.HideAll();
				}
				if (m_st != null)
				{
					m_st.SetOrreryDark(dark: false);
				}
				Enter(S.Dying);
				KitSelfTest.Note("win");
			}
		}

		protected override void OnCleanup()
		{
			ClearHitFilter();
			if ((Object)(object)Current == (Object)(object)this)
			{
				Current = null;
			}
			VaelStations.ImmuneUntil = -1f;
		}

		private static HitVerdict StaticFilter(Health health, DamageInfo info, bool hitFriendly)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			VaelBoss current = Current;
			if ((Object)(object)current == (Object)null || current.m_ward == null || (Object)(object)current.m_filteredHealth == (Object)null || health != current.m_filteredHealth)
			{
				return (HitVerdict)0;
			}
			return current.m_ward.Filter(health, info, hitFriendly);
		}

		private void ClearHitFilter()
		{
			try
			{
				if ((Object)(object)m_filteredHealth != (Object)null)
				{
					KitHealth.ClearFilter(m_filteredHealth);
				}
				if ((Object)(object)((KitBoss)this).LifeHealth != (Object)null && ((KitBoss)this).LifeHealth != m_filteredHealth)
				{
					KitHealth.ClearFilter(((KitBoss)this).LifeHealth);
				}
				m_filteredHealth = null;
			}
			catch (Exception ex)
			{
				Kit.Log.WarnOnce("vael clear filter", ex);
			}
		}

		protected override void KitUpdate()
		{
			float deltaTime = Time.deltaTime;
			if (m_st != null)
			{
				m_st.Update(deltaTime);
			}
			if (m_ward != null && (Object)(object)((KitBoss)this).LifeBody != (Object)null)
			{
				m_ward.UpdateSounds(((Component)((KitBoss)this).LifeBody).transform);
			}
			if (m_fx == null || Circles.Length < Geo.Circles.Length)
			{
				if ((Object)(object)((KitBoss)this).LifeBody != (Object)null && ((KitBoss)this).LifeBody.Alive)
				{
					((KitBoss)this).LifeBody.Brain.Stop();
				}
			}
			else
			{
				Tick(deltaTime);
			}
		}

		protected override void KitLateUpdate()
		{
			//IL_003a: 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_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_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: 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)
			if (m_fx != null && (!((Object)(object)((KitBoss)this).Arena != (Object)null) || ((Component)((KitBoss)this).Arena).gameObject.layer != 12))
			{
				float unpausedTime = ((KitBoss)this).UnpausedTime;
				KitBody lifeBody = ((KitBoss)this).LifeBody;
				Vector2 vaelP = Vector2.zero;
				if ((Object)(object)lifeBody != (Object)null && m_castCircle >= 0)
				{
					vaelP = Geo.ToCircle(((KitBoss)this).RoomLocal(((Component)lifeBody).transform.position), CastCentre);
				}
				bool flashOn = m_ward != null && unpausedTime - m_ward.FlashAt < 0.12f;
				bool flashAll = m_pulseAt >= 0f && InChannel && (InWindow(m_t - m_pulseAt, 0f, 0.12f) || InWindow(m_t - m_pulseAt, 0.25f, 0.12f));
				m_fx.Draw(unpausedTime, Time.deltaTime, Breach, vaelP, (m_ward != null) ? m_ward.FlashSeg : (-1), flashOn, flashAll, unpausedTime < m_chevronFlashUntil);
				m_spells.Draw();
				m_st.Draw(Breach, InChannel);
				if (m_state == S.Stunned && (Object)(object)lifeBody != (Object)null && lifeBody.Alive && m_t >= 0.55f && (Object)(object)lifeBody.Anim != (Object)null && !lifeBody.Anim.IsPlaying(((Object)Templates.Stunned).name))
				{
					lifeBody.Anim.Play(Templates.Stunned);
				}
			}
		}

		private static bool InWindow(float t, float start, float length)
		{
			if (t >= start)
			{
				return t < start + length;
			}
			return false;
		}

		private void Cut(exSpriteAnimClip clip, bool collisionOff = false)
		{
			KitBody lifeBody = ((KitBoss)this).LifeBody;
			if ((Object)(object)lifeBody != (Object)null && lifeBody.Alive && (Object)(object)clip != (Object)null)
			{
				lifeBody.Player.StartCutscene(clip, collisionOff, 0f);
			}
		}

		private void EndCut()
		{
			KitBody lifeBody = ((KitBoss)this).LifeBody;
			if ((Object)(object)lifeBody != (Object)null && lifeBody.Alive)
			{
				lifeBody.EndAction();
			}
		}

		public override bool GetVulnerable()
		{
			if (((Boss)this).GetAttackable())
			{
				if (m_state != S.Channel)
				{
					return m_state == S.Stunned;
				}
				return true;
			}
			return false;
		}

		public override Vector2 GetVulnerableTargetPosition()
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: 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_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: 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_006a: 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_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: 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_0086: 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_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(5f, -10f);
			KitBody lifeBody = ((KitBoss)this).LifeBody;
			if ((Object)(object)lifeBody == (Object)null)
			{
				return Vector2.op_Implicit(((Component)this).transform.position) - val;
			}
			Vector2 val2 = Vector2.op_Implicit(((Component)lifeBody).transform.position);
			if (m_state == S.Channel && m_castCircle >= 0 && Breach.Active)
			{
				Vector2 val3 = ((KitBoss)this).RoomLocal(Vector2.op_Implicit(val2));
				Player val4 = Util.Hero();
				Vector2 heroLocal = (((Object)(object)val4 != (Object)null) ? ((KitBoss)this).RoomLocal(((Component)val4).transform.position) : val3);
				Vector2 val5 = BotWaypoint(val3, heroLocal);
				return Vector2.op_Implicit(((KitBoss)this).World(val5)) - val;
			}
			return val2 - val;
		}

		internal Vector2 BotWaypoint(Vector2 vaelLocal, Vector2 heroLocal)
		{
			//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_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: 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_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: 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_007d: 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_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: 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_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			float num = ((Breach.Next != Breach.Cur) ? ((float)Breach.Next * 30f) : Breach.Centre);
			Vector2 castCentre = CastCentre;
			Vector2 val = Geo.RimPoint(castCentre, num) - castCentre;
			Vector2 val2 = -((Vector2)(ref val)).normalized;
			Vector2 val3 = heroLocal - vaelLocal;
			bool shortCut;
			if (((Vector2)(ref val3)).sqrMagnitude <= 0.0001f)
			{
				m_botSense = 0;
				return BotClampPoint(vaelLocal, val2, 26f, out shortCut);
			}
			float num2 = Vector2.Angle(val3, val2);
			if (num2 <= 50f)
			{
				m_botSense = 0;
				return vaelLocal;
			}
			if (num2 <= 60f)
			{
				m_botSense = 0;
				return BotClampPoint(vaelLocal, val2, 26f, out shortCut);
			}
			Vector2 normalized = ((Vector2)(ref val3)).normalized;
			if (m_botSense == 0 || m_botSenseNotch != num)
			{
				m_botSense = ChooseBotWay(vaelLocal, normalized, val2, num2);
				m_botSenseNotch = num;
			}
			return BotOrbitPoint(vaelLocal, normalized, m_botSense, out shortCut);
		}

		private static int ChooseBotWay(Vector2 vaelLocal, Vector2 bn, Vector2 side, float phi)
		{
			//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_000d: 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_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: 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_007f: 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_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			int num = ((bn.x * side.y - bn.y * side.x > 0f) ? 1 : (-1));
			int[] array = new int[2]
			{
				num,
				-num
			};
			float[] array2 = new float[2]
			{
				phi,
				360f - phi
			};
			int[] array3 = new int[2];
			float[] array4 = new float[2];
			for (int i = 0; i < 2; i++)
			{
				for (int j = 1; array2[i] - (float)j * 15f > 60f; j++)
				{
					Vector2 d = Geo.Rotate(bn, (float)(array[i] * j) * 15f);
					BotClampPoint(vaelLocal, d, Mathf.Max(26f, Geo.HitZoneExit(d, 12f)), out var shortCut);
					if (shortCut)
					{
						array3[i]++;
					}
				}
				array4[i] = Geo.Rotate(bn, (float)array[i] * 60f).y;
			}
			if (array3[0] != array3[1])
			{
				if (array3[0] >= array3[1])
				{
					return array[1];
				}
				return array[0];
			}
			if (array2[1] - array2[0] <= 40f)
			{
				if (!(array4[0] <= array4[1]))
				{
					return array[1];
				}
				return array[0];
			}
			return array[0];
		}

		private static Vector2 BotOrbitPoint(Vector2 vaelLocal, Vector2 bn, int sense, out bool shortCut)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: 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)
			Vector2 d = Geo.Rotate(bn, (float)sense * 60f);
			return BotClampPoint(vaelLocal, d, Mathf.Max(26f, Geo.HitZoneExit(d, 12f)), out shortCut);
		}

		private static Vector2 BotClampPoint(Vector2 vaelLocal, Vector2 d, float radius, out bool shortCut)
		{
			//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_0003: 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_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: 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_0041: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val = vaelLocal + d * radius;
			shortCut = false;
			int num = Mathf.CeilToInt(radius);
			for (int i = 0; i < num; i++)
			{
				if (Geo.OnFloor(val, 10f) && !Geo.InBlocker(val, 6f))
				{
					break;
				}
				shortCut = true;
				val = Vector2.MoveTowards(val, vaelLocal, 1f);
			}
			return val;
		}

		public override Vector2 GetNonVulnerableTargetPosition()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			return ((KitBoss)this).BotTarget();
		}
	}
	public sealed class VaelContactProbe : MonoBehaviour
	{
		private int m_motes;

		private void MsgOnAttackContact(DamageInfo damage)
		{
			if (m_motes >= 5 || !KitSelfTest.Active)
			{
				return;
			}
			try
			{
				if (damage != null && damage.m_source != null && !((Object)(object)damage.m_source.m_source == (Object)null) && !((Object)(object)Templates.MoteFx == (Object)null) && ((Object)damage.m_source.m_source).name.StartsWith(((Object)Templates.MoteFx).name, StringComparison.Ordinal))
				{
					Player val = Util.Hero();
					if (!((Object)(object)val == (Object)null) && !((Object)(object)damage.m_victim != (Object)(object)((Component)val).gameObject))
					{
						m_motes++;
						KitSelfTest.Note("mote contact " + m_motes + " (" + damage.m_amount.ToString("0.00") + " damage)");
					}
				}
			}
			catch (Exception ex)
			{
				Kit.Log.WarnOnce("vael contact probe", ex);
			}
		}
	}
	internal static class VaelCues
	{
		public static AudioCue BlinkOut;

		public static AudioCue BlinkIn;

		public static AudioCue Kindle;

		public static AudioCue Chant1;

		public static AudioCue Chant2;

		public static AudioCue Chant3;

		public static AudioCue Release;

		public static AudioCue Bolt;

		public static AudioCue WardPulse;

		public static AudioCue Tick;

		public static AudioCue Step;

		public static AudioCue Shove;

		public static AudioCue WardHold;

		public static AudioCue MotesAppear;

		public static AudioCue MotesFlare;

		public static AudioCue MotesPull;

		public static AudioCue DoubleAppear;

		public static AudioCue SwapWarn;

		public static AudioCue Swap;

		public static AudioCue SwapBurst;

		public static AudioCue Backlash;

		public static AudioCue Hurt;

		public static AudioCue Recite;

		public static AudioCue Death;

		public static AudioCue StaffFall;

		public static AudioCue GargoyleSpit;

		public static AudioCue GargoyleWake;

		public static AudioCue DustOn;

		public static AudioCue DustOff;

		public static bool Own { get; private set; }

		public static void Map(CueSet cues, KitLog log)
		{
			try
			{
				BlinkOut = cues.Need("VaelBlinkOut");
				BlinkIn = cues.Need("VaelBlinkIn");
				Kindle = cues.Need("VaelKindle");
				Chant1 = cues.Need("VaelChant1");
				Chant2 = cues.Need("VaelChant2");
				Chant3 = cues.Need("VaelChant3");
				Release = cues.Need("VaelRelease");
				Bolt = cues.Need("VaelBolt");
				WardPulse = cues.Need("VaelWardPulse");
				Tick = cues.Need("VaelTick");
				Step = cues.Need("VaelStep");
				Shove = cues.Need("VaelShove");
				WardHold = cues.Need("VaelWardHold");
				MotesAppear = cues.Need("VaelMotesAppear");
				MotesFlare = cues.Need("VaelMotesFlare");
				MotesPull = cues.Need("VaelMotesPull");
				DoubleAppear = cues.Need("VaelDoubleAppear");
				SwapWarn = cues.Need("VaelSwapWarn");
				Swap = cues.Need("VaelSwap");
				SwapBurst = cues.Need("VaelSwapBurst");
				Backlash = cues.Need("VaelBacklash");
				Hurt = cues.Need("VaelHurt");
				Recite = cues.Need("VaelRecite");
				Death = cues.Need("VaelDeath");
				StaffFall = cues.Need("VaelStaffFall");
				GargoyleSpit = cues.Need("VaelGargoyleSpit");
				GargoyleWake = cues.Need("VaelGargoyleWake");
				DustOn = cues.Need("VaelDustOn");
				DustOff = cues.Need("VaelDustOff");
				Own = true;
			}
			catch (Exception ex)
			{
				Own = false;
				if (log != null)
				{
					log.Warn("Vael's own sounds are not complete (" + ex.Message + "); every job uses its vanilla fallback");
				}
				Fallback();
			}
		}

		private static void Fallback()
		{
			AudioCue obj = Util.Cue("SoundPriestessTeleport1");
			AudioCue val = Util.Cue("SoundBossWizardConjure1");
			AudioCue wardHold = Util.Cue("SoundCrystalHit");
			AudioCue step = Util.Cue("SoundDoorCreakAnimated");
			AudioCue motesPull = Util.Cue("SoundTutBells3");
			AudioCue gargoyleWake = Util.Cue("SoundGargoyleTurnToStone");
			AudioCue dustOff = Util.Cue("SoundGargoyleStoneLand");
			BlinkOut = (BlinkIn = obj);
			Kindle = Util.Cue("SoundFlameOn");
			Chant1 = (Chant2 = (Chant3 = val));
			Release = val;
			Bolt = Util.Cue("SoundSkelMageProjectile");
			WardPulse = Util.Cue("SoundChallengeSpawnShockwave");
			Tick = (Step = step);
			Shove = (WardHold = wardHold);
			MotesAppear = (MotesFlare = (MotesPull = motesPull));
			SwapBurst = obj;
			Swap = obj;
			SwapWarn = obj;
			DoubleAppear = obj;
			Backlash = Util.Cue("SoundDeathExplosionSmall");
			Hurt = Util.Cue("SoundBossBTakeDamage");
			Recite = Util.Cue("SoundBossBIntro3");
			Death = Util.Cue("SoundBossHydraBodyDeathStart");
			StaffFall = Util.Cue("SoundSkelBoneLand");
			GargoyleSpit = (GargoyleWake = gargoyleWake);
			DustOn = (DustOff = dustOff);
		}

		public static AudioCue Chant(int phase)
		{
			if (phase < 3)
			{
				if (phase != 2)
				{
					return Chant1;
				}
				return Chant2;
			}
			return Chant3;
		}

		public static AudioSource Play(AudioCue cue, Transform at)
		{
			if ((Object)(object)cue == (Object)null)
			{
				return null;
			}
			try
			{
				return ((Object)(object)at != (Object)null) ? SystemAudio.Play(cue, at) : SystemAudio.Play(cue);
			}
			catch (Exception ex)
			{
				Kit.Log.WarnOnce("vael sound " + ((Object)cue).name, ex);
				return null;
			}
		}
	}
	internal static class EnvArt
	{
		internal enum SheetId
		{
			Env,
			Rim,
			Fx,
			Unused
		}

		internal struct Entry
		{
			public string File;

			public int W;

			public int H;

			public int Frames;

			public int Cols;

			public int Rows;

			public SheetId Sheet;
		}

		internal static readonly Entry[] Table = new Entry[58]
		{
			S("VaelFloor", 280, 125, 1, SheetId.Env),
			S("VaelBackWall", 280, 51, 1, SheetId.Env),
			S("VaelCircle_dark", 64, 40, 1, SheetId.Env),
			S("VaelCircle_kindle", 64, 40, 8, SheetId.Env),
			S("VaelCircle_lit", 64, 40, 4, SheetId.Env),
			S("VaelCircle_shatter", 64, 40, 5, SheetId.Env),
			S("VaelCircle_broken", 64, 40, 1, SheetId.Env),
			G("VaelRim_dark", 64, 40, 24, 1, SheetId.Unused),
			G("VaelRim_lit", 64, 40, 24, 1, SheetId.Rim),
			G("VaelRim_bright", 64, 40, 24, 1, SheetId.Rim),
			G("VaelRim_flash", 64, 40, 24, 1, SheetId.Rim),
			G("VaelRim_open", 64, 40, 24, 3, SheetId.Rim),
			G("VaelRim_danger", 64, 40, 24, 2, SheetId.Rim),
			S("VaelRimSmall", 8, 3, 6, SheetId.Unused),
			S("VaelBracket", 5, 9, 2, SheetId.Env),
			S("VaelChevron", 7, 5, 2, SheetId.Unused),
			S("VaelChevron8", 7, 7, 16, SheetId.Env),
			S("VaelRuneSpark", 7, 7, 4, SheetId.Env),
			S("VaelLandingRune", 24, 14, 6, SheetId.Env),
			S("VaelRimShard", 5, 5, 4, SheetId.Env),
			S("VaelBacklashFlash", 88, 56, 4, SheetId.Env),
			S("VaelBrazier_inactive", 24, 44, 6, SheetId.Env),
			S("VaelBrazier_activate", 24, 44, 3, SheetId.Env),
			S("VaelBrazier_active", 24, 44, 4, SheetId.Env),
			S("VaelBrazier_action", 24, 44, 6, SheetId.Env),
			S("VaelBrazier_deactivate", 24, 44, 3, SheetId.Env),
			S("VaelBrazier_greyedOut", 24, 44, 1, SheetId.Env),
			S("VaelOrrery_inactive", 40, 44, 6, SheetId.Env),
			S("VaelOrrery_activate", 40, 44, 3, SheetId.Env),
			S("VaelOrrery_active", 40, 44, 4, SheetId.Env),
			S("VaelOrrery_action", 40, 44, 6, SheetId.Env),
			S("VaelOrrery_deactivate", 40, 44, 3, SheetId.Env),
			S("VaelOrrery_greyedOut", 40, 44, 1, SheetId.Env),
			S("VaelGargoyleR_inactive", 32, 40, 6, SheetId.Env),
			S("VaelGargoyleR_activate", 32, 40, 3, SheetId.Env),
			S("VaelGargoyleR_active", 32, 40, 4, SheetId.Env),
			S("VaelGargoyleR_action", 32, 40, 6, SheetId.Env),
			S("VaelGargoyleR_deactivate", 32, 40, 3, SheetId.Env),
			S("VaelGargoyleR_greyedOut", 32, 40, 1, SheetId.Env),
			S("VaelGargoyleL_inactive", 32, 40, 6, SheetId.Env),
			S("VaelGargoyleL_activate", 32, 40, 3, SheetId.Env),
			S("VaelGargoyleL_active", 32, 40, 4, SheetId.Env),
			S("VaelGargoyleL_action", 32, 40, 6, SheetId.Env),
			S("VaelGargoyleL_deactivate", 32, 40, 3, SheetId.Env),
			S("VaelGargoyleL_greyedOut", 32, 40, 1, SheetId.Env),
			S("VaelOrreryRing", 40, 44, 12, SheetId.Env),
			S("VaelOrreryRingBrass", 40, 44, 12, SheetId.Env),
			S("VaelGargoyleWakeR", 32, 40, 6, SheetId.Env),
			S("VaelGargoyleWakeL", 32, 40, 6, SheetId.Env),
			S("VaelBolt", 54, 30, 11, SheetId.Fx),
			S("VaelBoltParticle", 54, 30, 8, SheetId.Fx),
			S("VaelMote", 54, 30, 11, SheetId.Fx),
			S("VaelMoteParticle", 54, 30, 8, SheetId.Unused),
			S("VaelMoteFlare", 54, 30, 11, SheetId.Fx),
			S("VaelStoneBolt", 27, 15, 18, SheetId.Fx),
			S("VaelStoneBoltParticle", 27, 15, 7, SheetId.Fx),
			S("VaelStoneFlecks", 20, 36, 4, SheetId.Env),
			S("VaelDustFall", 20, 36, 6, SheetId.Env)
		};

		public static Sheet Env;

		public static Sheet Rim;

		public static Sheet Fx;

		public static exSpriteAnimClip CircleKindle;

		public static exSpriteAnimClip CircleLit;

		public static exSpriteAnimClip CircleShatter;

		public static exSpriteAnimClip RuneSpark;

		public static exSpriteAnimClip LandingRune;

		public static exSpriteAnimClip RimShard;

		public static exSpriteAnimClip BacklashFlash;

		public static exSpriteAnimClip GargoyleWakeL;

		public static exSpriteAnimClip GargoyleWakeR;

		public static exSpriteAnimClip StoneFlecks;

		public static exSpriteAnimClip DustFall;

		public static Dictionary<string, exSpriteAnimClip> BrazierStates;

		public static Dictionary<string, exSpriteAnimClip> OrreryStates;

		public static Dictionary<string, exSpriteAnimClip> GargoyleRStates;

		public static Dictionary<string, exSpriteAnimClip> GargoyleLStates;

		public static readonly float[] StationFps = new float[6] { 4f, 8f, 6f, 10f, 8f, 6f };

		public static readonly float[] GargoyleFps = new float[6] { 4f, 8f, 6f, 12f, 8f, 6f };

		public const float GargoyleAttackAt = 0.1f;

		public static float BrazierActionTime
		{
			get
			{
				Entry[] table = Table;
				for (int i = 0; i < table.Length; i++)
				{
					Entry entry = table[i];
					if (entry.File == "VaelBrazier_action")
					{
						return (float)entry.Frames / StationFps[3];
					}
				}
				return 0.6f;
			}
		}

		private static Entry S(string file, int w, int h, int frames, SheetId sheet)
		{
			return new Entry
			{
				File = file,
				W = w,
				H = h,
				Frames = frames,
				Cols = 0,
				Rows = 0,
				Sheet = sheet
			};
		}

		private static Entry G(string file, int w, int h, int cols, int rows, SheetId sheet)
		{
			return new Entry
			{
				File = file,
				W = w,
				H = h,
				Frames = cols * rows,
				Cols = cols,
				Rows = rows,
				Sheet = sheet
			};
		}

		public static void Build(BossContext ctx, Material envMaterial, Material fxMaterial, AudioCue spitCue)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Expected O, but got Unknown
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			Env = new Sheet("VaelEnv");
			Rim = new Sheet("VaelRim");
			Fx = new Sheet("VaelFx");
			Entry[] table = Table;
			for (int i = 0; i < table.Length; i++)
			{
				Entry entry = table[i];
				if (entry.Sheet != SheetId.Unused)
				{
					Sheet val = ((entry.Sheet == SheetId.Env) ? Env : ((entry.Sheet == SheetId.Rim) ? Rim : Fx));
					string text = "VaelEnv." + entry.File + ".png";
					Texture2D val2 = ctx.Assets.Png(text);
					int num = ((entry.Cols > 0) ? (entry.W * entry.Cols) : (entry.W * entry.Frames));
					int num2 = ((entry.Rows > 0) ? (entry.H * entry.Rows) : entry.H);
					if (((Texture)val2).width != num || ((Texture)val2).height != num2)
					{
						throw new FormatException(text + " is " + ((Texture)val2).width + "x" + ((Texture)val2).height + ", the table expects " + num + "x" + num2);
					}
					if (entry.Cols > 0)
					{
						val.AddGrid(entry.File, ctx.Assets, text, entry.Cols, entry.Rows);
					}
					else
					{
						val.AddStrip(entry.File, val2, entry.Frames);
					}
				}
			}
			Env.Build(envMaterial);
			Rim.Build(envMaterial);
			Fx.Build(((Object)(object)fxMaterial != (Object)null) ? fxMaterial : envMaterial);
			CircleKindle = Env.Clip("VaelCircle_kindle", "VaelCircle_kindle", 8f, (WrapMode)1, (IEnumerable<EventInfo>)null, (int[])null);
			CircleLit = Env.Clip("VaelCircle_lit", "VaelCircle_lit", 6f, (WrapMode)2, (IEnumerable<EventInfo>)null, (int[])null);
			CircleShatter = Env.Clip("VaelCircle_shatter", "VaelCircle_shatter", 10f, (WrapMode)1, (IEnumerable<EventInfo>)null, (int[])null);
			RuneSpark = Env.Clip("VaelRuneSpark", "VaelRuneSpark", 10f, (WrapMode)2, (IEnumerable<EventInfo>)null, (int[])null);
			LandingRune = Env.Clip("VaelLandingRune", "VaelLandingRune", 8.5f, (WrapMode)1, (IEnumerable<EventInfo>)null, (int[])null);
			RimShard = Env.Clip("VaelRimShard", "VaelRimShard", 12f, (WrapMode)2, (IEnumerable<EventInfo>)null, (int[])null);
			BacklashFlash = Env.Clip("VaelBacklashFlash", "VaelBacklashFlash", 12f, (WrapMode)1, (IEnumerable<EventInfo>)null, (int[])null);
			GargoyleWakeL = Env.Clip("VaelGargoyleWakeL", "VaelGargoyleWakeL", 8f, (WrapMode)1, (IEnumerable<EventInfo>)null, (int[])null);
			GargoyleWakeR = Env.Clip("VaelGargoyleWakeR", "VaelGargoyleWakeR", 8f, (WrapMode)1, (IEnumerable<EventInfo>)null, (int[])null);
			StoneFlecks = Env.Clip("VaelStoneFlecks", "VaelStoneFlecks", 8f, (WrapMode)2, (IEnumerable<EventInfo>)null, (int[])null);
			DustFall = Env.Clip("VaelDustFall", "VaelDustFall", 10f, (WrapMode)1, (IEnumerable<EventInfo>)null, (int[])null);
			BrazierStates = KitArt.TrapStateClips(Env, "VaelBrazier", StationFps);
			OrreryStates = KitArt.TrapStateClips(Env, "VaelOrrery", StationFps);
			GargoyleRStates = GargoyleClips("VaelGargoyleR", spitCue);
			GargoyleLStates = GargoyleClips("VaelGargoyleL", spitCue);
		}

		private static Dictionary<string, exSpriteAnimClip> GargoyleClips(string prefix, AudioCue spitCue)
		{
			Dictionary<string, exSpriteAnimClip> dictionary = new Dictionary<string, exSpriteAnimClip>();
			for (int i = 0; i < KitArt.TrapStates.Length; i++)
			{
				string text = KitArt.TrapStates[i];
				bool flag = text == "inactive" || text == "active";
				List<EventInfo> list = null;
				if (text == "action")
				{
					list = new List<EventInfo>
					{
						KitArt.Event(0.1f, "AnimAttack", 0),
						KitArt.Sound(0.1f, spitCue)
					};
				}
				dictionary[text] = Env.Clip(prefix + "_" + text, prefix + "_" + text, GargoyleFps[i], (WrapMode)((!flag) ? 1 : 2), (IEnumerable<EventInfo>)list, (int[])null);
			}
			return dictionary;
		}

		public static int RimFrame(string key, int k, int row)
		{
			int[] array = Rim.Frames(key);
			int num = row * 24 + k;
			return array[Mathf.Clamp(num, 0, array.Length - 1)];
		}

		public static int EnvFrame(string key, int frame)
		{
			int[] array = Env.Frames(key);
			return array[Mathf.Clamp(frame, 0, array.Length - 1)];
		}

		public static int FrameCount(Sheet sheet, string key)
		{
			return sheet.Frames(key).Length;
		}
	}
	internal static class Geo
	{
		public static readonly Vector2 BossStart = new Vector2(0f, 20f);

		public static readonly Vector2 BarLocal = new Vector2(0f, 100f);

		public static readonly Vector2 FloorLocal = new Vector2(0f, -5f);

		public static readonly Vector2 BackWallLocal = new Vector2(0f, 82f);

		public static readonly Vector2[] Circles = (Vector2[])(object)new Vector2[4]
		{
			new Vector2(-52f, 16f),
			new Vector2(52f, 16f),
			new Vector2(-86f, -24f),
			new Vector2(86f, -24f)
		};

		public static readonly string[] CircleNames = new string[4] { "NW", "NE", "SW", "SE" };

		public static readonly Vector2[] Braziers = (Vector2[])(object)new Vector2[4]
		{
			new Vector2(-22f, 48f),
			new Vector2(22f, 48f),
			new Vector2(-114f, 8f),
			new Vector2(114f, 8f)
		};

		public static readonly Vector2 Orrery = new Vector2(0f, -8f);

		public static readonly Vector2[] Gargoyles = (Vector2[])(object)new Vector2[4]
		{
			new Vector2(-125f, 37f),
			new Vector2(125f, 41f),
			new Vector2(-133f, -30f),
			new Vector2(133f, -30f)
		};

		public static readonly bool[] GargoyleFacesRight = new bool[4] { true, false, true, false };

		public static readonly Vector2[] GargoyleRange = (Vector2[])(object)new Vector2[4]
		{
			new Vector2(-75f, 15f),
			new Vector2(165f, 255f),
			new Vector2(-30f, 60f),
			new Vector2(120f, 210f)
		};

		public const int DormantGargoyle = 3;

		public static readonly Vector2 MouthRight = new Vector2(13.5f, 22.5f);

		public static readonly Vector2 MouthLeft = new Vector2(-13.5f, 22.5f);

		public static readonly Vector2 BrazierSeat = new Vector2(0f, 12f);

		public static readonly Rect BrazierBlocker = new Rect(-7f, -4f, 14f, 8f);

		public static readonly Vector2 OrrerySeat = new Vector2(0f, 27f);

		public static readonly Rect OrreryBlocker = new Rect(-10f, -4f, 20f, 8f);

		public static readonly Vector2[] Polygon = (Vector2[])(object)new Vector2[16]
		{
			new Vector2(122.41f, -48.53f),
			new Vector2(95f, -63.82f),
			new Vector2(70f, -67f),
			new Vector2(-58f, -67f),
			new Vector2(-111.9f, -56.38f),
			new Vector2(-133.4f, -32.59f),
			new Vector2(-138.39f, -3.18f),
			new Vector2(-136.8f, 28.21f),
			new Vector2(-114.8f, 44.4f),
			new Vector2(-60.54f, 54.31f),
			new Vector2(5.02f, 56.3f),
			new Vector2(47.58f, 55.3f),
			new Vector2(98.34f, 49.36f),
			new Vector2(133.37f, 35.9f),
			new Vector2(139.24f, 5.83f),
			new Vector2(132.97f, -31.93f)
		};

		public static float EdgeDistance(Vector2 p)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: 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_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_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: 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_0050: 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_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_0063: Unknown result type (might be due to invalid IL or missing references)
			float num = float.MaxValue;
			for (int i = 0; i < Polygon.Length; i++)
			{
				Vector2 val = Polygon[i];
				Vector2 val2 = Polygon[(i + 1) % Polygon.Length] - val;
				float num2 = Mathf.Clamp01(Vector2.Dot(p - val, val2) / ((Vector2)(ref val2)).sqrMagnitude);
				float num3 = num;
				Vector2 val3 = p - (val + val2 * num2);
				num = Mathf.Min(num3, ((Vector2)(ref val3)).magnitude);
			}
			return num;
		}

		public static bool InPolygon(Vector2 p)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: 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_0048: 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_0055: 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_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: 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)
			bool flag = false;
			int num = 0;
			int num2 = Polygon.Length - 1;
			while (num < Polygon.Length)
			{
				Vector2 val = Polygon[num];
				Vector2 val2 = Polygon[num2];
				if (val.y > p.y != val2.y > p.y && p.x < (val2.x - val.x) * (p.y - val.y) / (val2.y - val.y) + val.x)
				{
					flag = !flag;
				}
				num2 = num++;
			}
			return flag;
		}

		public static bool InBlocker(Vector2 p, float pad)
		{
			//IL_001e: 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_0023: 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)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: 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_006b: 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_0083: 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)
			for (int i = 0; i <= Braziers.Length; i++)
			{
				Vector2 val = ((i < Braziers.Length) ? Braziers[i] : Orrery);
				Rect val2 = ((i < Braziers.Length) ? BrazierBlocker : OrreryBlocker);
				if (p.x >= val.x + ((Rect)(ref val2)).xMin - pad && p.x <= val.x + ((Rect)(ref val2)).xMax + pad && p.y >= val.y + ((Rect)(ref val2)).yMin - pad && p.y <= val.y + ((Rect)(ref val2)).yMax + pad)
				{
					return true;
				}
			}
			return false;
		}

		public static bool CapsuleInBlocker(Vector2 root, float pad)
		{
			//IL_000f: 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_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: 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_005a: 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_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: 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_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			float num = 2f;
			Vector2 val = default(Vector2);
			for (int i = -1; i <= 1; i += 2)
			{
				((Vector2)(ref val))..ctor(root.x + (float)i * num, root.y + 2.5f);
				for (int j = 0; j <= Braziers.Length; j++)
				{
					Vector2 val2 = ((j < Braziers.Length) ? Braziers[j] : Orrery);
					Rect val3 = ((j < Braziers.Length) ? BrazierBlocker : OrreryBlocker);
					float num2 = Mathf.Max(Mathf.Max(val2.x + ((Rect)(ref val3)).xMin - val.x, 0f), val.x - (val2.x + ((Rect)(ref val3)).xMax));
					float num3 = Mathf.Max(Mathf.Max(val2.y + ((Rect)(ref val3)).yMin - val.y, 0f), val.y - (val2.y + ((Rect)(ref val3)).yMax));
					if (num2 * num2 + num3 * num3 < (5f + pad) * (5f + pad))
					{
						return true;
					}
				}
			}
			return false;
		}

		public static bool OnFloor(Vector2 p, float margin)
		{
			//IL_0000: 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)
			if (InPolygon(p))
			{
				return EdgeDistance(p) >= margin;
			}
			return false;
		}

		public static Vector2 Rotate(Vector2 v, float deg)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			float num = deg * ((float)Math.PI / 180f);
			float num2 = Mathf.Cos(num);
			float num3 = Mathf.Sin(num);
			return new Vector2(v.x * num2 - v.y * num3, v.x * num3 + v.y * num2);
		}

		public static float HitZoneExit(Vector2 d, f

plugins/CrawlCustomBosses/GoblinKingBoss.dll

Decompiled 4 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BossKit;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("GoblinKingBoss")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("GoblinKingBoss")]
[assembly: AssemblyTitle("GoblinKingBoss")]
[assembly: AssemblyVersion("1.0.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 GoblinKingBoss
{
	internal enum CartMode
	{
		Cruise,
		Fetch,
		Halted,
		Braked
	}
	internal enum BrakePhase
	{
		None,
		Skid,
		Stand,
		Pull
	}
	internal struct CartSim
	{
		public float S;

		public float V;

		public int Dir;

		public CartMode Mode;

		public float Cruise;

		public bool Panic;

		public float HaltS;

		public float FetchMax;

		public BrakePhase Brake;

		public float BrakeTimer;

		public float BrakeDecel;

		public float CruiseTarget => Cruise * (Panic ? 1.25f : 1f);

		public bool Moving => V > 0.01f;

		public void HaltAt(float s, float vmax)
		{
			Mode = CartMode.Fetch;
			HaltS = RailLine.Wrap(s);
			FetchMax = vmax;
			Brake = BrakePhase.None;
		}

		public bool StartBrake()
		{
			if (Mode != CartMode.Cruise)
			{
				return false;
			}
			Mode = CartMode.Braked;
			if (V > 0.01f)
			{
				Brake = BrakePhase.Skid;
				BrakeDecel = V * V / 16f;
			}
			else
			{
				V = 0f;
				Brake = BrakePhase.Stand;
				BrakeTimer = 1.2f;
			}
			return true;
		}

		public bool Step(float dt)
		{
			bool result = false;
			switch (Mode)
			{
			case CartMode.Cruise:
				V = Mathf.MoveTowards(V, CruiseTarget, 120f * dt);
				S = RailLine.Wrap(S + (float)Dir * V * dt);
				break;
			case CartMode.Fetch:
			{
				float num = RailLine.Ahead(S, HaltS, Dir);
				if (num < 0.05f)
				{
					S = HaltS;
					V = 0f;
					Mode = CartMode.Halted;
					result = true;
					break;
				}
				float num2 = FetchMax * Mathf.Sqrt(Mathf.Min(1f, num / 8f));
				V = Mathf.Min(Mathf.MoveTowards(V, FetchMax, 120f * dt), num2);
				float num3 = V * dt;
				if (num3 >= num)
				{
					S = HaltS;
					V = 0f;
					Mode = CartMode.Halted;
					result = true;
				}
				else
				{
					S = RailLine.Wrap(S + (float)Dir * num3);
				}
				break;
			}
			case CartMode.Halted:
				V = 0f;
				break;
			case CartMode.Braked:
				switch (Brake)
				{
				case BrakePhase.Skid:
					V = Mathf.Max(0f, V - BrakeDecel * dt);
					S = RailLine.Wrap(S + (float)Dir * V * dt);
					if (V <= 0f)
					{
						Brake = BrakePhase.Stand;
						BrakeTimer = 1.2f;
					}
					break;
				case BrakePhase.Stand:
					V = 0f;
					BrakeTimer -= dt;
					if (BrakeTimer <= 0f)
					{
						Brake = BrakePhase.Pull;
						BrakeTimer = 0f;
					}
					break;
				case BrakePhase.Pull:
					BrakeTimer += dt;
					V = CruiseTarget * Mathf.Min(1f, BrakeTimer / 0.5f);
					S = RailLine.Wrap(S + (float)Dir * V * dt);
					if (BrakeTimer >= 0.5f)
					{
						Brake = BrakePhase.None;
						Mode = CartMode.Cruise;
					}
					break;
				default:
					Mode = CartMode.Cruise;
					break;
				}
				break;
			}
			return result;
		}

		public CartSim After(float t, float dt)
		{
			CartSim result = this;
			while (t > 1E-05f)
			{
				float num = Mathf.Min(dt, t);
				result.Step(num);
				t -= num;
			}
			return result;
		}

		public CartSim AfterBraking(float t, float dt, float brakeIn)
		{
			if (brakeIn < 0f || brakeIn > t)
			{
				return After(t, dt);
			}
			CartSim cartSim = After(brakeIn, dt);
			cartSim.StartBrake();
			return cartSim.After(t - brakeIn, dt);
		}

		public CartSim Steps(int n, float dt)
		{
			CartSim result = this;
			for (int i = 0; i < n; i++)
			{
				result.Step(dt);
			}
			return result;
		}

		public float Behind(float back)
		{
			return RailLine.Wrap(S - (float)Dir * back);
		}

		public float AheadOf(float ahead)
		{
			return RailLine.Wrap(S + (float)Dir * ahead);
		}
	}
	internal static class Landing
	{
		public static Vector2 Predict(float sBlast, int dir, Vector2 hero)
		{
			//IL_0003: 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_000b: 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_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: 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_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_00a0: 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_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			Vector2 tangent;
			Vector2 val = RailLine.At(sBlast, out tangent);
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(0f - tangent.y, tangent.x);
			float num = Vector2.Dot(val2, hero - val);
			float num2 = ((!(Mathf.Abs(num) < 6f)) ? ((num > 0f) ? 1f : (-1f)) : ((ArenaPoly.EdgeDist(val + val2 * 34f) >= ArenaPoly.EdgeDist(val - val2 * 34f)) ? 1f : (-1f)));
			return ArenaPoly.ClampToward(val + val2 * (num2 * 34f) + tangent * ((float)dir * 10f), val, 16f);
		}
	}
	internal static class Forms
	{
		public const float SeatedRadius = 8f;

		public const float SeatedHeight = 40f;

		public static readonly Vector3 SeatedCentre = new Vector3(0f, 6f, 0f);

		public static readonly Vector3 SeatedHitZone = new Vector3(50f, 50f, 64f);

		public static readonly Vector3 SeatedHitPos = new Vector3(0f, 25f, -8f);

		public const float FootRadius = 7f;

		public const float FootHeight = 14f;

		public static readonly Vector3 FootCentre = new Vector3(0f, 6f, 0f);

		public static readonly Vector3 FootHitZone = new Vector3(22f, 34f, 64f);

		public static readonly Vector3 FootHitPos = new Vector3(0f, 17f, -8f);

		public static void Seated(KitBody body)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			Apply(body, 15, 8f, 40f, SeatedCentre, SeatedHitZone, SeatedHitPos);
			SetIdleRun(body, Templates.Body["GrukkSeatRoll"], Templates.Body["GrukkSeatRoll"]);
			body.HoldVulnerable = false;
		}

		public static void OnFoot(KitBody body)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			Apply(body, 16, 7f, 14f, FootCentre, FootHitZone, FootHitPos);
			SetIdleRun(body, Templates.Body["GrukkIdle"], Templates.Body["GrukkWaddle"]);
			body.HoldVulnerable = true;
		}

		private static void Apply(KitBody body, int layer, float radius, float height, Vector3 centre, Vector3 hitScale, Vector3 hitPos)
		{
			//IL_0061: 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_008b: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)body == (Object)null || (Object)(object)body.Player == (Object)null)
			{
				return;
			}
			try
			{
				((Component)body).gameObject.layer = layer;
				Util.Set((object)body.Player, "m_originalLayer", (object)layer);
				CapsuleCollider component = ((Component)body).GetComponent<CapsuleCollider>();
				if ((Object)(object)component != (Object)null)
				{
					component.direction = 0;
					component.radius = radius;
					component.height = height;
					component.center = centre;
				}
				Transform val = ((Component)body).transform.Find("HitZone");
				if ((Object)(object)val != (Object)null)
				{
					val.localScale = hitScale;
					val.localPosition = hitPos;
				}
			}
			catch (Exception ex)
			{
				Plugin.Ctx.Log.WarnOnce("grukk form", ex);
			}
		}

		public static void SetIdleRun(KitBody body, exSpriteAnimClip idle, exSpriteAnimClip run)
		{
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Invalid comparison between Unknown and I4
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Invalid comparison between Unknown and I4
			if ((Object)(object)body == (Object)null || (Object)(object)body.Player == (Object)null)
			{
				return;
			}
			try
			{
				Util.Set((object)body.Player, "m_animationIdle", (object)idle);
				Util.Set((object)body.Player, "m_animationRun", (object)run);
				exSpriteAnimation anim = body.Anim;
				if ((Object)(object)anim != (Object)null)
				{
					if (anim.GetAnimation(((Object)idle).name) == null)
					{
						anim.AddAnimation(idle);
					}
					if (anim.GetAnimation(((Object)run).name) == null)
					{
						anim.AddAnimation(run);
					}
					ePlayerState state = body.Player.GetState();
					exSpriteAnimClip val = (((int)state == 3) ? run : (((int)state == 2) ? idle : null));
					if ((Object)(object)val != (Object)null && !anim.IsPlaying(((Object)val).name))
					{
						anim.Play(val);
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Ctx.Log.WarnOnce("grukk idle run", ex);
			}
		}
	}
	internal static class Fx
	{
		public static GameObject SpawnOwned(GameObject template, Vector3 world, float angleDeg, GameObject owner, float scale = 1f, Transform parent = null)
		{
			//IL_000d: 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_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Expected O, but got Unknown
			if ((Object)(object)template == (Object)null)
			{
				return null;
			}
			try
			{
				GameObject val = ExtentionsMethodsPool.SpawnBegin(template, new Vector3(world.x, world.y, 0f), Quaternion.Euler(0f, 0f, angleDeg));
				if ((Object)(object)val == (Object)null)
				{
					return null;
				}
				if (!Mathf.Approximately(scale, 1f))
				{
					val.transform.localScale = new Vector3(scale, scale, 1f);
				}
				if ((Object)(object)parent != (Object)null)
				{
					val.transform.SetParent(parent, true);
				}
				val.SendMessage(Constants.MSG_SETSPAWNER, (object)new DamageSource(val, owner, (PlayerData)null, -1, -1, (ValueModifierStack)null, false), (SendMessageOptions)1);
				ExtentionsMethodsPool.SpawnFinalize(val);
				return val;
			}
			catch (Exception ex)
			{
				Plugin.Ctx.Log.WarnOnce("spawn " + ((Object)template).name, ex);
				return null;
			}
		}

		public static void SetLife(GameObject go, float seconds)
		{
			if ((Object)(object)go == (Object)null)
			{
				return;
			}
			try
			{
				Effect component = go.GetComponent<Effect>();
				if ((Object)(object)component != (Object)null)
				{
					Util.Set((object)component, "m_destroyAfterTime", (object)seconds);
					Util.Set((object)component, "m_destroyOnAnimEnd", (object)false);
				}
			}
			catch (Exception ex)
			{
				Plugin.Ctx.Log.WarnOnce("fx life", ex);
			}
		}

		public static void Avoid(Room room, Vector2 local, float seconds, GameObject owner)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)Templates.Avoid == (Object)null) && !((Object)(object)room == (Object)null))
			{
				SetLife(SpawnOwned(Templates.Avoid, KitRoom.World(room, local), 0f, owner), Mathf.Max(0.05f, seconds));
			}
		}

		public static void Despawn(GameObject go)
		{
			if ((Object)(object)go == (Object)null)
			{
				return;
			}
			try
			{
				ExtentionsMethodsPool.Despawn(go);
			}
			catch (Exception ex)
			{
				Plugin.Ctx.Log.WarnOnce("despawn " + ((Object)go).name, ex);
			}
		}
	}
	public sealed class GrukkBrain : KitBrain
	{
	}
	internal sealed class GrukkBodyEvents : MonoBehaviour
	{
		public GrukkBoss Boss;

		private void EvLob()
		{
			if ((Object)(object)Boss != (Object)null)
			{
				Boss.OnEvLob();
			}
		}

		private void EvSwat()
		{
			if ((Object)(object)Boss != (Object)null)
			{
				Boss.OnEvSwat();
			}
		}

		private void EvSlap()
		{
			if ((Object)(object)Boss != (Object)null)
			{
				Boss.OnEvSlap();
			}
		}

		private void EvThrowCrown()
		{
			if ((Object)(object)Boss != (Object)null)
			{
				Boss.OnEvThrow(crown: true);
			}
		}

		private void EvThrowScepter()
		{
			if ((Object)(object)Boss != (Object)null)
			{
				Boss.OnEvThrow(crown: false);
			}
		}
	}
	public sealed class GrukkBoss : KitBoss
	{
		internal enum King
		{
			Intro,
			Seated,
			Arc,
			Dazed,
			Walking,
			Denied,
			Towed,
			Climb,
			Failsafe,
			Beat,
			Dead
		}

		[CompilerGenerated]
		private static class <>O
		{
			public static HitFilter <0>__Filter;
		}

		private RailCart m_cart;

		private King m_king;

		private float m_kingTime;

		private float m_armedAt;

		private float m_nextLob;

		private float m_nextSwat;

		private float m_nextSlap;

		private exSpriteAnimClip m_seatClip;

		private bool m_tinted;

		private float m_maxSeatErr;

		private float m_seatErrLogged = -10f;

		private int m_snaps;

		private Vector2 m_lastMark;

		private bool m_markValid;

		private bool m_polyChecked;

		private static readonly Color Phase3Tint = new Color(0.85f, 0.1f, 0.05f, 0.35f);

		private bool m_lobPending;

		private HeldCue m_lobCue;

		private HeldCue m_swatCue;

		private HeldCue m_slapCue;

		internal bool KnotsProven;

		private float m_dryClock;

		private int m_fallbackHits;

		private bool m_fallbackOpen;

		private static readonly FieldInfo s_actionableIndicator = typeof(PropTrap).GetField("m_actionableIndicator", BindingFlags.Instance | BindingFlags.NonPublic);

		private bool m_dark;

		private float m_arcClock;

		private float m_climbClock;

		private Vector2 m_arcFrom;

		private Vector2 m_arcTo;

		private Vector2 m_climbFrom;

		private bool m_beat;

		private bool m_pendingBeat;

		private bool m_beatWhistled;

		private bool m_beatFetched;

		private int m_beatStep;

		private int m_beatPhase;

		private float m_onFootClock;

		private float m_onFootLimit = 8f;

		private float m_nextPlan;

		private float m_deniedUntil;

		private bool m_passDenied;

		private Vector2 m_goal;

		private float m_remountS;

		private float m_remountStart;

		private float m_whistleUntil;

		private Vector2 m_towDir;

		private float m_towLeft;

		private GrukkHook m_hook;

		private float m_arcOffset;

		private bool m_barging;

		private readonly List<GrukkThrown> m_throws = new List<GrukkThrown>();

		private KitStation m_towerA;

		private KitStation m_towerB;

		private KitStation m_brake;

		private KitStation m_gallows;

		private readonly float[] m_pourStart = new float[2] { -100f, -100f };

		private readonly float[] m_delugeSoundAt = new float[2] { -1f, -1f };

		private exSprite m_gaugeA;

		private exSprite m_gaugeB;

		private float m_brakeBiteAt = -1f;

		private float m_gallowsFireAt = -1f;

		private float m_brakeLastWanted;

		private static readonly TowerView[] s_towers = new TowerView[2];

		private bool m_towerBGrey;

		private bool m_wantGrey;

		private int m_lateFrames;

		private bool m_towerBDeep;

		internal bool Seated
		{
			get
			{
				if (m_king != King.Seated)
				{
					return m_king == King.Intro;
				}
				return true;
			}
		}

		internal bool KnotsLightable
		{
			get
			{
				if (m_king == King.Seated && ((KitBoss)this).Fighting)
				{
					return !m_beat;
				}
				return false;
			}
		}

		internal float BodyZ
		{
			get
			{
				//IL_001f: Unknown result type (might be due to invalid IL or missing references)
				if (!((Object)(object)((KitBoss)this).LifeBody != (Object)null))
				{
					return 0f;
				}
				return ((Component)((KitBoss)this).LifeBody).transform.position.z;
			}
		}

		internal Vector2 KingLocal
		{
			get
			{
				//IL_0020: Unknown result type (might be due to invalid IL or missing references)
				//IL_0025: Unknown result type (might be due to invalid IL or missing references)
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				if (!((Object)(object)((KitBoss)this).LifeBody != (Object)null))
				{
					return Vector2.zero;
				}
				return ((KitBoss)this).RoomLocal(((Component)((KitBoss)this).LifeBody).transform.position);
			}
		}

		internal bool RamLive
		{
			get
			{
				if (m_king != King.Dead)
				{
					return !((KitBoss)this).Killed;
				}
				return false;
			}
		}

		internal bool TowActive => m_king == King.Towed;

		internal bool CanBeHooked
		{
			get
			{
				if (((KitBoss)this).Fighting && !m_beat)
				{
					if (m_king != King.Dazed && m_king != King.Walking)
					{
						return m_king == King.Denied;
					}
					return true;
				}
				return false;
			}
		}

		private bool KingOnFootForBots
		{
			get
			{
				if (m_king != King.Dazed && m_king != King.Walking)
				{
					return m_king == King.Denied;
				}
				return true;
			}
		}

		internal bool HeroLocal(out Vector2 p)
		{
			//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_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			Player val = Util.Hero();
			if ((Object)(object)val == (Object)null || (Object)(object)val.GetHealthComponent() == (Object)null || !val.GetHealthComponent().IsAlive())
			{
				p = Vector2.zero;
				return false;
			}
			p = ((KitBoss)this).RoomLocal(((Component)val).transform.position);
			return true;
		}

		private static float CruiseFor(int phase)
		{
			if (phase < 3)
			{
				if (phase != 2)
				{
					return 44f;
				}
				return 50f;
			}
			return 56f;
		}

		private static float SparkFor(int phase)
		{
			if (phase < 3)
			{
				return 11f;
			}
			return 12.7f;
		}

		private static float OnFootLimitFor(int phase)
		{
			if (phase < 3)
			{
				if (phase != 2)
				{
					return 8f;
				}
				return 7f;
			}
			return 6f;
		}

		protected override void BuildArena(Room room)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: 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_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			KnotsProven = false;
			m_dryClock = 0f;
			m_fallbackHits = 0;
			m_fallbackOpen = false;
			Sheet sheet = Templates.Env.Sheet;
			Decal(room, sheet, "GrukkRails", 0, Tuning.RailsCentre, (Anchor)4, 5.9f);
			Decal(room, sheet, "GrukkStraw", 0, Tuning.StrawTop, (Anchor)4, 5.8f);
			Decal(room, sheet, "GrukkStraw", 1, Tuning.StrawBottom, (Anchor)4, 5.8f);
			Decal(room, sheet, "GrukkLoot", 2, new Vector2(70f, -22f), (Anchor)7, 5.8f);
			Decal(room, sheet, "GrukkLoot", 2, new Vector2(-66f, -20f), (Anchor)7, 5.8f);
			KitArt.CreateSprite(((Component)room).transform, sheet, "GrukkLoot", 0, ((KitBoss)this).World(new Vector2(80f, -9f)), (Anchor)7, true, 0f);
			KitArt.CreateSprite(((Component)room).transform, sheet, "GrukkLoot", 1, ((KitBoss)this).World(new Vector2(94f, -20f)), (Anchor)7, true, 0f);
			KitArt.CreateSprite(((Component)room).transform, sheet, "GrukkLoot", 1, ((KitBoss)this).World(new Vector2(-98f, -18f)), (Anchor)7, true, 0f);
			m_cart = RailCart.Create(this, room, 405f, 1, 44f);
			m_cart.Blasted += OnBlast;
			m_cart.Halted += OnCartHalted;
			m_cart.Doused += OnDoused;
			BuildStations(room);
			CheckPoly(room);
		}

		private void Decal(Room room, Sheet sheet, string key, int frame, Vector2 local, Anchor anchor, float z)
		{
			//IL_000b: 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_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			exSprite obj = KitArt.CreateSprite(((Component)room).transform, sheet, key, frame, ((KitBoss)this).World(local), anchor, false, 0f);
			Vector3 position = ((Component)obj).transform.position;
			((Component)obj).transform.position = new Vector3(position.x, position.y, z);
		}

		private void CheckPoly(Room room)
		{
			//IL_002d: 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_004d: 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)
			if (m_polyChecked)
			{
				return;
			}
			m_polyChecked = true;
			int num = 0;
			int num2 = 0;
			Vector2 val = default(Vector2);
			for (float num3 = -136f; num3 <= 136f; num3 += 8f)
			{
				for (float num4 = -64f; num4 <= 54f; num4 += 8f)
				{
					((Vector2)(ref val))..ctor(num3, num4);
					if (!(Mathf.Abs(ArenaPoly.EdgeDist(val)) < 3f))
					{
						num2++;
						if (ArenaPoly.Inside(val) != room.IsPointInRoom(Vector2.op_Implicit(((KitBoss)this).World(val))))
						{
							num++;
						}
					}
				}
			}
			if (num > 0)
			{
				((KitBoss)this).Ctx.Log.Warn("Grukk's arena polygon disagrees with the room at " + num + " of " + num2 + " sample points");
			}
			KitSelfTest.Note("arena polygon check: " + num + " of " + num2 + " disagree");
		}

		protected override KitBody SpawnBodies(Room room)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Expected O, but got Unknown
			KitBody val = KitBodies.Spawn<GrukkBrain>((KitBoss)(object)this, Templates.BodyTemplate, RailLine.Seat(((Object)(object)m_cart != (Object)null) ? m_cart.Sim.S : 405f), "Grukk");
			((Component)val).gameObject.AddComponent<GrukkBodyEvents>().Boss = this;
			val.SetHurtSound(Sfx.Get("GrukkHurt"), 0.25f);
			val.KeepInRoom = true;
			val.GuardStuns = true;
			val.RefuseStatuses = true;
			val.ScaleEffect(Templates.SwatFx, 1.6f);
			val.ScaleEffect(Templates.SlapFx, 1.2f);
			if ((Object)(object)m_cart == (Object)null)
			{
				((KitBoss)this).Ctx.Log.Error("Grukk's cart was not built: he stands still and can be beaten where he stands");
				KitSelfTest.Note("no cart: Grukk stands open to blows");
				Forms.OnFoot(val);
				m_king = King.Walking;
				return val;
			}
			HealthRules.Refuse = RefuseHits;
			HealthRules.OnFoot = OpenToBlows;
			HealthRules.Observe = ObserveHit;
			Health health = val.Health;
			object obj = <>O.<0>__Filter;
			if (obj == null)
			{
				HitFilter val2 = HealthRules.Filter;
				<>O.<0>__Filter = val2;
				obj = (object)val2;
			}
			KitHealth.SetFilter(health, (HitFilter)obj);
			val.VelocityOverride = SeatDrive;
			Forms.Seated(val);
			m_seatClip = Templates.Body["GrukkSeatRoll"];
			m_king = King.Intro;
			m_cart.ArmRam(((Component)val).gameObject);
			return val;
		}

		private bool RefuseHits()
		{
			if (m_king != King.Arc && m_king != King.Climb && !m_beat && m_king != King.Intro)
			{
				return m_king == King.Dead;
			}
			return true;
		}

		private bool OpenToBlows()
		{
			if (m_king != King.Dazed && m_king != King.Walking && m_king != King.Denied && m_king != King.Towed)
			{
				return m_king == King.Failsafe;
			}
			return true;
		}

		protected override IEnumerator Intro()
		{
			if ((Object)(object)m_cart == (Object)null)
			{
				yield return KitBoss.WaitGameTime(1f);
				yield break;
			}
			m_cart.Sim.HaltAt(445.4f, 44f);
			float t = 0f;
			while (m_cart.Sim.Mode == CartMode.Fetch && t < 3f)
			{
				yield return null;
				t += Time.deltaTime;
			}
			if ((Object)(object)((KitBoss)this).LifeBody != (Object)null && ((KitBoss)this).LifeBody.Alive)
			{
				((KitBoss)this).LifeBody.PlayStatus(Templates.Body["GrukkLurch"]);
			}
			Sfx.Play("GrukkBrakeSkid", ((Component)m_cart).transform);
			Sfx.Play("GrukkCackle", ((Object)(object)((KitBoss)this).LifeBody != (Object)null) ? ((Component)((KitBoss)this).LifeBody).transform : ((Component)this).transform);
			yield return KitBoss.WaitGameTime(1.2f);
		}

		protected override void OnFightStart()
		{
			if (!((Object)(object)m_cart == (Object)null) && !((Object)(object)((KitBoss)this).LifeBody == (Object)null))
			{
				m_cart.Sim.Cruise = CruiseFor(((KitBoss)this).Phase);
				m_cart.Sim.Mode = CartMode.Cruise;
				m_cart.Snuff(FuseState.Fresh, 1.5f);
				m_armedAt = ((KitBoss)this).UnpausedTime + 1f;
				m_nextLob = m_armedAt;
				m_nextSwat = m_armedAt;
				SetKing(King.Seated);
			}
		}

		private void SetKing(King k)
		{
			m_king = k;
			m_kingTime = 0f;
		}

		protected override void KitUpdate()
		{
			//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_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: 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_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: 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)
			KitBody lifeBody = ((KitBoss)this).LifeBody;
			if ((Object)(object)m_cart == (Object)null || (Object)(object)lifeBody == (Object)null)
			{
				return;
			}
			float deltaTime = Time.deltaTime;
			m_kingTime += deltaTime;
			UpdateStationLocks();
			UpdateDelugeSounds();
			if (lifeBody.Alive && (m_king == King.Intro || m_king == King.Seated))
			{
				SyncSeatClip(lifeBody);
			}
			if (((KitBoss)this).Fighting && lifeBody.Alive && m_king != King.Dead)
			{
				Vector2 p;
				bool heroAlive = HeroLocal(out p);
				Vector2 kingLocal = KingLocal;
				UpdateTimedPresses(kingLocal);
				switch (m_king)
				{
				case King.Seated:
					UpdateSeated(lifeBody, kingLocal, p, heroAlive);
					break;
				case King.Arc:
					UpdateArc(lifeBody);
					break;
				case King.Dazed:
					UpdateDazed(lifeBody, deltaTime);
					break;
				case King.Walking:
					UpdateWalking(lifeBody, kingLocal, p, heroAlive, deltaTime);
					break;
				case King.Denied:
					UpdateDenied(lifeBody, kingLocal, p, heroAlive, deltaTime);
					break;
				case King.Towed:
					UpdateTowed(lifeBody, kingLocal, p, heroAlive, deltaTime);
					break;
				case King.Climb:
					UpdateClimb(lifeBody);
					break;
				case King.Failsafe:
				case King.Beat:
					UpdateRemount(lifeBody, kingLocal, p, heroAlive);
					break;
				}
				UpdateMark(p);
				UpdateBrakeIdle();
			}
		}

		protected override void KitLateUpdate()
		{
			UpdateDormantLook();
			UpdateTowerBDepth();
			UpdateGauges();
			UpdateArcSprite();
		}

		private Vector3? SeatDrive()
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: 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_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: 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_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: 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_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			KitBody lifeBody = ((KitBoss)this).LifeBody;
			if ((Object)(object)lifeBody == (Object)null || (Object)(object)m_cart == (Object)null || (Object)(object)((KitBoss)this).Arena == (Object)null)
			{
				return null;
			}
			float fixedDeltaTime = Time.fixedDeltaTime;
			Vector2 kingLocal = KingLocal;
			switch (m_king)
			{
			case King.Intro:
			case King.Seated:
				return Toward(lifeBody, kingLocal, RailLine.Seat(m_cart.Sim.S), fixedDeltaTime, seat: true);
			case King.Arc:
			{
				m_arcClock += fixedDeltaTime;
				float num = Mathf.Clamp01(m_arcClock / 0.7f);
				return Toward(lifeBody, kingLocal, Vector2.Lerp(m_arcFrom, m_arcTo, num), fixedDeltaTime, seat: false);
			}
			case King.Climb:
			{
				m_climbClock += fixedDeltaTime;
				float num2 = Mathf.Clamp01(m_climbClock / 0.5f);
				return Toward(lifeBody, kingLocal, Vector2.Lerp(m_climbFrom, RailLine.Seat(m_cart.Sim.S), num2), fixedDeltaTime, seat: false);
			}
			case King.Towed:
				return TowStep(kingLocal, fixedDeltaTime);
			case King.Dazed:
			case King.Denied:
				return Vector3.zero;
			case King.Beat:
				if (m_beatStep != 0)
				{
					return null;
				}
				return Vector3.zero;
			case King.Dead:
				return Vector3.zero;
			default:
				return null;
			}
		}

		private Vector3 Toward(KitBody body, Vector2 pos, Vector2 target, float dt, bool seat)
		{
			//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_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_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_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: 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)
			Vector2 val = target - pos;
			float magnitude = ((Vector2)(ref val)).magnitude;
			if (seat)
			{
				m_maxSeatErr = Mathf.Max(m_maxSeatErr, magnitude);
			}
			if (magnitude > 4f && seat)
			{
				Vector3 val2 = ((KitBoss)this).World(target);
				body.Body.position = new Vector3(val2.x, val2.y, ((Component)body).transform.position.z);
				m_snaps++;
				if (((KitBoss)this).UnpausedTime - m_seatErrLogged > 1f)
				{
					m_seatErrLogged = ((KitBoss)this).UnpausedTime;
					((KitBoss)this).Ctx.Log.Info("Grukk's seat drive snapped (error " + magnitude.ToString("0.0") + ", " + m_snaps + " snaps so far)");
				}
				return Vector3.zero;
			}
			return new Vector3(val.x / dt, val.y / dt, 0f);
		}

		private void UpdateSeated(KitBody body, Vector2 king, Vector2 hero, bool heroAlive)
		{
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Invalid comparison between Unknown and I4
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Invalid comparison between Unknown and I4
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			if (m_cart.Fuse.State == FuseState.Spent)
			{
				((KitBoss)this).Ctx.Log.WarnOnce("grukk spent seated", "Grukk sat on a spent fuse; it was renewed");
				m_cart.Snuff(FuseState.Fresh, 1.5f);
			}
			if (m_cart.Sim.Mode == CartMode.Halted)
			{
				m_cart.Sim.Mode = CartMode.Cruise;
			}
			if (m_cart.Fuse.State == FuseState.Dry && KnotsLightable)
			{
				m_dryClock += Time.deltaTime;
			}
			bool flag = m_cart.Fuse.State == FuseState.Lit;
			if (!heroAlive)
			{
				return;
			}
			body.Brain.Face(hero - king);
			if (flag || ((KitBoss)this).UnpausedTime < m_armedAt || m_cart.Sim.Mode == CartMode.Fetch || m_cart.Sim.Mode == CartMode.Halted)
			{
				return;
			}
			ePlayerState state = body.Player.GetState();
			if ((int)state != 2 && (int)state != 3)
			{
				return;
			}
			Vector2 tangent;
			Vector2 val = RailLine.At(m_cart.Sim.S, out tangent);
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(0f - tangent.y, tangent.x);
			Vector2 val3 = hero - val;
			float num = Mathf.Abs(Vector2.Dot(val3, tangent));
			float num2 = Mathf.Abs(Vector2.Dot(val3, val2));
			if (((KitBoss)this).UnpausedTime >= m_nextSwat && num2 <= 26f && num <= 24f)
			{
				if (body.Brain.RequestAttack(0))
				{
					m_nextSwat = ((KitBoss)this).UnpausedTime + 1.6f;
					m_swatCue = Sfx.Keep("GrukkSwat", ((Component)body).transform);
					Fx.Avoid(((KitBoss)this).Arena, val + val2 * (Mathf.Sign(Vector2.Dot(val3, val2)) * 18f), 0.6f, ((Component)body).gameObject);
				}
				return;
			}
			Vector2 val4 = hero - king;
			float magnitude = ((Vector2)(ref val4)).magnitude;
			if (((KitBoss)this).UnpausedTime >= m_nextLob && magnitude >= 40f && magnitude <= 180f)
			{
				body.PlayStatus(Templates.Body["GrukkLob"]);
				m_lobCue = Sfx.Keep("GrukkLob", ((Component)body).transform);
				m_lobPending = true;
				m_nextLob = ((KitBoss)this).UnpausedTime + ((((KitBoss)this).Phase >= 3) ? 2.4f : ((((KitBoss)this).Phase == 2) ? 3f : 2.8f));
			}
		}

		private void SyncSeatClip(KitBody body)
		{
			exSpriteAnimClip val = ((m_cart.Fuse.State == FuseState.Lit) ? Templates.Body["GrukkPanic"] : ((!m_cart.Sim.Moving && !((Object)(object)Templates.SeatStop == (Object)null)) ? Templates.SeatStop : Templates.Body["GrukkSeatRoll"]));
			if ((Object)(object)val != (Object)(object)m_seatClip)
			{
				m_seatClip = val;
				Forms.SetIdleRun(body, val, val);
			}
		}

		private void CutWindups()
		{
			Sfx.Cut(ref m_lobCue);
			Sfx.Cut(ref m_swatCue);
			Sfx.Cut(ref m_slapCue);
		}

		internal void OnEvLob()
		{
			//IL_006a: 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_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: 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_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: 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_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: 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_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: 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_0143: 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_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: 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_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: 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_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!m_lobPending || m_king != King.Seated || m_cart.Fuse.State == FuseState.Lit || !((KitBoss)this).Fighting)
				{
					Sfx.Cut(ref m_lobCue);
					return;
				}
				m_lobPending = false;
				if (!HeroLocal(out var p))
				{
					Sfx.Cut(ref m_lobCue);
					return;
				}
				m_lobCue = null;
				Player val = Util.Hero();
				Vector2 val2 = Vector2.zero;
				Rigidbody val3 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<Rigidbody>() : null);
				if ((Object)(object)val3 != (Object)null)
				{
					val2 = Vector2.op_Implicit(val3.velocity);
				}
				Vector2 val4 = val2 * 0.5f;
				if (((Vector2)(ref val4)).magnitude > 30f)
				{
					val4 = ((Vector2)(ref val4)).normalized * 30f;
				}
				Vector2 kingLocal = KingLocal;
				Vector2 fromLocal = kingLocal + new Vector2(0f, 60f);
				Vector2 val5 = ArenaPoly.ClampInside(p + val4, 8f);
				if (((KitBoss)this).Phase >= 2)
				{
					Vector2 val6 = val5 - kingLocal;
					Vector2 val7;
					if (!(((Vector2)(ref val6)).sqrMagnitude > 0.01f))
					{
						val7 = Vector2.right;
					}
					else
					{
						Vector2 val8 = new Vector2(0f - val6.y, val6.x);
						val7 = ((Vector2)(ref val8)).normalized;
					}
					Vector2 val9 = val7;
					GrukkLobFlight.Launch(((KitBoss)this).Arena, fromLocal, ArenaPoly.ClampInside(val5 + val9 * 15f, 8f), ((Component)((KitBoss)this).LifeBody).gameObject);
					GrukkLobFlight.Launch(((KitBoss)this).Arena, fromLocal, ArenaPoly.ClampInside(val5 - val9 * 15f, 8f), ((Component)((KitBoss)this).LifeBody).gameObject);
				}
				else
				{
					GrukkLobFlight.Launch(((KitBoss)this).Arena, fromLocal, val5, ((Component)((KitBoss)this).LifeBody).gameObject);
				}
			}
			catch (Exception ex)
			{
				((KitBoss)this).Ctx.Log.WarnOnce("grukk lob event", ex);
			}
		}

		internal void OnEvSwat()
		{
			m_swatCue = null;
		}

		internal void OnEvSlap()
		{
			m_slapCue = null;
		}

		internal void OnKnotHit(int i)
		{
			//IL_0098: 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_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Invalid comparison between Unknown and I4
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Invalid comparison between Unknown and I4
			if (!KnotsLightable || m_cart.Fuse.State != FuseState.Dry)
			{
				return;
			}
			m_cart.Light(i, SparkFor(((KitBoss)this).Phase));
			Sfx.Play("GrukkFuseLight", ((Component)m_cart).transform);
			Sfx.Play("GrukkPanic", ((Object)(object)((KitBoss)this).LifeBody != (Object)null) ? ((Component)((KitBoss)this).LifeBody).transform : ((Component)this).transform);
			m_lobPending = false;
			CutWindups();
			if ((Object)(object)((KitBoss)this).LifeBody != (Object)null)
			{
				ePlayerState state = ((KitBoss)this).LifeBody.Player.GetState();
				((KitBoss)this).LifeBody.Brain.Stop();
				if ((int)state == 15)
				{
					((KitBoss)this).LifeBody.EndAction();
				}
				else if ((int)state == 4)
				{
					((KitBoss)this).LifeBody.Player.StartCutscene(true, false);
					((KitBoss)this).LifeBody.Player.EndCutscene();
				}
			}
			KitSelfTest.Note("lit knot " + i switch
			{
				1 => "middle", 
				0 => "far", 
				_ => "near", 
			} + " in phase " + ((KitBoss)this).Phase);
		}

		private void ObserveHit(DamageInfo info)
		{
			//IL_0109: 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_010f: 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)
			if (KnotsProven || info == null || info.m_amount <= 0f || info.m_isDamageFromStatus || !KitHealth.IsHeroHit(info) || (Object)(object)m_cart == (Object)null || !KnotsLightable || m_cart.Fuse.State != FuseState.Dry)
			{
				return;
			}
			m_fallbackHits++;
			if (!m_fallbackOpen)
			{
				if ((float)m_fallbackHits < 8f || m_dryClock < 30f)
				{
					return;
				}
				m_fallbackOpen = true;
				((KitBoss)this).Ctx.Log.Warn("No hero blow has reached a fuse knot after " + m_dryClock.ToString("0") + " s on a dry fuse and " + m_fallbackHits + " blows on the seated king: the knots' contact does not work here, so blows on the seated king light the nearest knot");
				KitSelfTest.Note("knot fallback opened (no hero blow reached a knot)");
			}
			if (!HeroLocal(out var p))
			{
				return;
			}
			int i = 0;
			float num = float.MaxValue;
			for (int j = 0; j < 3; j++)
			{
				Vector2 val = m_cart.KnotPoint(j) - p;
				float sqrMagnitude = ((Vector2)(ref val)).sqrMagnitude;
				if (sqrMagnitude < num)
				{
					num = sqrMagnitude;
					i = j;
				}
			}
			OnKnotHit(i);
		}

		private void OnDoused(int tower)
		{
			KitSelfTest.Note("doused by tower " + ((tower == 0) ? "A" : "B"));
		}

		private void UpdateMark(Vector2 hero)
		{
			//IL_006c: 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_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: 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_001a: Unknown result type (might be due to invalid IL or missing references)
			if (m_cart.Fuse.State != FuseState.Lit)
			{
				m_cart.SetMark(on: false, Vector2.zero, fast: false);
				return;
			}
			float fixedDeltaTime = Time.fixedDeltaTime;
			float timeToBlast = m_cart.Fuse.TimeToBlast;
			CartSim cartSim = m_cart.Sim.Steps(m_cart.Fuse.StepsToBlast(fixedDeltaTime), fixedDeltaTime);
			Vector2 roomLocal = (m_lastMark = Landing.Predict(cartSim.S, cartSim.Dir, hero));
			m_markValid = true;
			m_cart.SetMark(on: true, roomLocal, timeToBlast < 0.8f);
		}

		private void OnCartHalted()
		{
			if (m_king == King.Dead || ((KitBoss)this).Killed || ((KitBoss)this).Won)
			{
				m_cart.Stop();
			}
		}

		protected override void OnPhase(int phase)
		{
			//IL_0078: 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)
			if ((Object)(object)m_towerB != (Object)null && !m_towerB.Dormant)
			{
				DormantLook(m_towerB, grey: false);
			}
			if ((Object)(object)m_cart != (Object)null)
			{
				m_cart.Sim.Cruise = CruiseFor(phase);
			}
			if (phase >= 3 && !m_tinted && (Object)(object)((KitBoss)this).LifeBody != (Object)null)
			{
				m_tinted = true;
				try
				{
					KitArt.AddTint(((Component)((KitBoss)this).LifeBody).gameObject, Phase3Tint);
					if ((Object)(object)m_cart != (Object)null)
					{
						m_cart.Tint(Phase3Tint);
					}
				}
				catch (Exception ex)
				{
					((KitBoss)this).Ctx.Log.WarnOnce("grukk tint", ex);
				}
			}
			if (!((Object)(object)m_cart == (Object)null) && !((Object)(object)((KitBoss)this).LifeBody == (Object)null))
			{
				if (OpenToBlows())
				{
					StartBeat(phase);
				}
				else
				{
					m_pendingBeat = true;
				}
			}
		}

		protected override void OnBossDying(DamageInfo info)
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			King king = m_king;
			m_king = King.Dead;
			m_beat = false;
			CutWindups();
			EndTow();
			if ((Object)(object)m_cart != (Object)null)
			{
				m_cart.Snuff(FuseState.Spent, 0f);
				m_cart.SetMark(on: false, Vector2.zero, fast: false);
				m_cart.SmokeHopper(1.2f);
				if (m_cart.Sim.Moving)
				{
					m_cart.Sim.HaltAt(m_cart.Sim.AheadOf(8f), Mathf.Max(10f, m_cart.Sim.V));
				}
				else
				{
					m_cart.Stop();
				}
				m_cart.ShowEmpty = true;
			}
			Sfx.Play("GrukkDeath", ((Object)(object)((KitBoss)this).LifeBody != (Object)null) ? ((Component)((KitBoss)this).LifeBody).transform : ((Component)this).transform);
			StationsDark();
			KitSelfTest.Note("killed while " + king.ToString() + "; max seat error " + m_maxSeatErr.ToString("0.00") + ", snaps " + m_snaps);
		}

		private void StationsDark()
		{
			KitStation[] array = (KitStation[])(object)new KitStation[4] { m_towerA, m_towerB, m_brake, m_gallows };
			string[] array2 = new string[4] { "GrukkTowerA", "GrukkTowerB", "GrukkBrake", "GrukkGallows" };
			for (int i = 0; i < array.Length; i++)
			{
				KitStation val = array[i];
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				try
				{
					if ((Object)(object)val.States != (Object)null)
					{
						((Behaviour)val.States).enabled = false;
					}
					exSpriteAnimation component = ((Component)val).GetComponent<exSpriteAnimation>();
					exSpriteAnimClip val2 = Templates.Env[array2[i] + "_greyedOut"];
					if ((Object)(object)component != (Object)null && (Object)(object)val2 != (Object)null)
					{
						if (component.GetAnimation(((Object)val2).name) == null)
						{
							component.AddAnimation(val2);
						}
						component.Play(val2);
					}
					if ((Object)(object)val.Trap != (Object)null)
					{
						GameObject directionIndicator = val.Trap.GetDirectionIndicator();
						if ((Object)(object)directionIndicator != (Object)null)
						{
							directionIndicator.SetActive(false);
						}
						GameObject val3 = (GameObject)(((object)s_actionableIndicator != null) ? /*isinst with value type is only supported in some contexts*/: null);
						if ((Object)(object)val3 != (Object)null)
						{
							val3.SetActive(false);
						}
					}
				}
				catch (Exception ex)
				{
					((KitBoss)this).Ctx.Log.WarnOnce("grukk stations dark", ex);
				}
			}
			if ((Object)(object)m_gaugeA != (Object)null)
			{
				((Component)m_gaugeA).gameObject.SetActive(false);
			}
			if ((Object)(object)m_gaugeB != (Object)null)
			{
				((Component)m_gaugeB).gameObject.SetActive(false);
			}
			m_dark = true;
		}

		protected override void OnHeroKilledKit(Player hero)
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			EndTow();
			SetBarging(((KitBoss)this).LifeBody, on: false);
			if ((Object)(object)m_cart != (Object)null)
			{
				m_cart.Snuff((m_cart.Fuse.State == FuseState.Spent) ? FuseState.Spent : FuseState.Steaming, 999f);
				m_cart.SetMark(on: false, Vector2.zero, fast: false);
				if (m_cart.Sim.Moving)
				{
					m_cart.Sim.HaltAt(m_cart.Sim.AheadOf(8f), Mathf.Max(10f, m_cart.Sim.V));
				}
				else
				{
					m_cart.Stop();
				}
			}
			if (m_king == King.Climb && (Object)(object)m_cart != (Object)null && (Object)(object)((KitBoss)this).LifeBody != (Object)null && ((KitBoss)this).LifeBody.Alive)
			{
				Forms.Seated(((KitBoss)this).LifeBody);
				((KitBoss)this).LifeBody.EndAction();
				m_cart.ShowEmpty = false;
				m_seatClip = Templates.Body["GrukkSeatRoll"];
				if (m_beat)
				{
					m_beat = false;
					if ((Object)(object)((KitBoss)this).LifeHealth != (Object)null)
					{
						((KitBoss)this).LifeHealth.StopInvincibility("Beat");
					}
				}
				SetKing(King.Seated);
			}
			if ((Object)(object)((KitBoss)this).LifeBody != (Object)null && ((KitBoss)this).LifeBody.Alive)
			{
				((KitBoss)this).LifeBody.Brain.Stop();
				if (Seated)
				{
					Sfx.Cut(ref m_lobCue);
					Sfx.Cut(ref m_swatCue);
					((KitBoss)this).LifeBody.PlayStatus(Templates.Body["GrukkLurch"]);
				}
				else
				{
					EndLoopingStatus(((KitBoss)this).LifeBody);
				}
				Sfx.Play("GrukkCackle", ((Component)((KitBoss)this).LifeBody).transform);
			}
		}

		private static void EndLoopingStatus(KitBody body)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Invalid comparison between Unknown and I4
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Invalid comparison between Unknown and I4
			if ((int)body.Player.GetState() == 15 && !((Object)(object)body.Anim == (Object)null))
			{
				exSpriteAnimState currentAnimation = body.Anim.GetCurrentAnimation();
				if (currentAnimation != null && (int)currentAnimation.wrapMode == 2)
				{
					body.EndAction();
				}
			}
		}

		protected override void OnCleanup()
		{
			HealthRules.Refuse = null;
			HealthRules.OnFoot = null;
			HealthRules.Observe = null;
			if ((Object)(object)((KitBoss)this).LifeHealth != (Object)null)
			{
				KitHealth.ClearFilter(((KitBoss)this).LifeHealth);
			}
			EndTow();
		}

		private void OnBlast(float sBlast)
		{
			//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_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: 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_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			KitBody lifeBody = ((KitBoss)this).LifeBody;
			if ((Object)(object)lifeBody == (Object)null || !lifeBody.Alive || m_king != King.Seated || !((KitBoss)this).Fighting)
			{
				return;
			}
			try
			{
				Vector2 val = RailLine.At(m_cart.Sim.Behind(19f));
				Fx.SpawnOwned(Templates.BackfireFx, ((KitBoss)this).World(val), 0f, ((Component)lifeBody).gameObject, Templates.BackfireScale);
				Sfx.Play("GrukkBackfire", ((Component)m_cart).transform);
				m_cart.SmokeHopper(2f);
				Vector2 kingLocal = KingLocal;
				if (!HeroLocal(out var p))
				{
					p = kingLocal;
				}
				Vector2 val2 = Landing.Predict(sBlast, m_cart.Sim.Dir, p);
				string[] obj = new string[5]
				{
					"blast in phase ",
					((KitBoss)this).Phase.ToString(),
					": Crown Mark ",
					null,
					null
				};
				object obj2;
				if (!m_markValid)
				{
					obj2 = "none";
				}
				else
				{
					Vector2 val3 = m_lastMark - val2;
					obj2 = ((Vector2)(ref val3)).magnitude.ToString("0.0");
				}
				obj[3] = (string)obj2;
				obj[4] = " from the landing";
				KitSelfTest.Note(string.Concat(obj));
				m_markValid = false;
				m_arcFrom = kingLocal;
				m_arcTo = val2;
				m_arcClock = 0f;
				m_lobPending = false;
				CutWindups();
				m_cart.EmptyFlipped = ((Component)lifeBody).transform.localScale.x < 0f;
				lifeBody.EndAction();
				lifeBody.Brain.Stop();
				Forms.OnFoot(lifeBody);
				m_seatClip = null;
				lifeBody.PlayCutscene(Templates.Body["GrukkUnthroned"], true);
				Sfx.Play("GrukkUnthroned", ((Component)lifeBody).transform);
				m_cart.ShowEmpty = true;
				SetKing(King.Arc);
			}
			catch (Exception ex)
			{
				((KitBoss)this).Ctx.Log.WarnOnce("grukk blast", ex);
				if (m_king == King.Seated && (Object)(object)m_cart != (Object)null)
				{
					m_cart.Snuff(FuseState.Fresh, 1.5f);
				}
			}
		}

		private void UpdateArc(KitBody body)
		{
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			if (!(m_arcClock < 0.7f))
			{
				body.Stun(1f, Templates.Body["GrukkDazed"]);
				Sfx.Play("GrukkLand", ((Component)body).transform);
				m_onFootClock = 0f;
				m_onFootLimit = OnFootLimitFor(((KitBoss)this).Phase);
				m_deniedUntil = 0f;
				m_passDenied = false;
				m_nextPlan = 0f;
				RefreshGoal(KingLocal, 1f);
				SetKing(King.Dazed);
			}
		}

		private void RefreshGoal(Vector2 king, float walkDelay)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)m_cart == (Object)null) && !(((KitBoss)this).UnpausedTime < m_nextPlan))
			{
				m_nextPlan = ((KitBoss)this).UnpausedTime + 0.25f;
				Planner.CatchPoint(king, m_cart.Sim, Mathf.Max(0f, m_deniedUntil - ((KitBoss)this).UnpausedTime), Mathf.Max(0f, walkDelay), out m_goal, out var _);
			}
		}

		private void UpdateArcSprite()
		{
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			KitBody lifeBody = ((KitBoss)this).LifeBody;
			if ((Object)(object)lifeBody == (Object)null)
			{
				return;
			}
			exSprite component = ((Component)lifeBody).GetComponent<exSprite>();
			if (!((Object)(object)component == (Object)null))
			{
				float num = 0f;
				if (m_king == King.Arc)
				{
					float num2 = Mathf.Clamp01(m_arcClock / 0.7f);
					num = Mathf.Round(48f * num2 * (1f - num2));
				}
				if (!Mathf.Approximately(num, m_arcOffset))
				{
					m_arcOffset = num;
					((exPlane)component).offset = new Vector2(0f, num);
				}
			}
		}

		private bool CommonFoot(float dt)
		{
			if (m_pendingBeat)
			{
				StartBeat(((KitBoss)this).Phase);
				return true;
			}
			m_onFootClock += dt;
			if (m_onFootClock >= m_onFootLimit)
			{
				StartFailsafe();
				return true;
			}
			return false;
		}

		private void UpdateDazed(KitBody body, float dt)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			if (!CommonFoot(dt))
			{
				RefreshGoal(KingLocal, 1f - m_kingTime);
				if (m_kingTime >= 1f)
				{
					m_nextPlan = 0f;
					SetKing(King.Walking);
				}
			}
		}

		private void UpdateWalking(KitBody body, Vector2 king, Vector2 hero, bool heroAlive, float dt)
		{
			//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)
			//IL_0017: 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_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Invalid comparison between Unknown and I4
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Invalid comparison between Unknown and I4
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			if (CommonFoot(dt))
			{
				return;
			}
			Vector2 val = m_cart.RearPoint();
			Vector2 val2 = val - king;
			float magnitude = ((Vector2)(ref val2)).magnitude;
			if (magnitude <= 14f)
			{
				if (!m_passDenied || !m_cart.Sim.Moving)
				{
					if (Planner.StepBlocked(king, val, hero, heroAlive))
					{
						Deny(body);
					}
					else
					{
						StartClimb(barge: false);
					}
					return;
				}
			}
			else if (magnitude > 16f)
			{
				m_passDenied = false;
			}
			ePlayerState state = body.Player.GetState();
			if (((int)state == 2 || (int)state == 3) && !TrySlap(body, king, hero, heroAlive))
			{
				RefreshGoal(king, 0f);
				WalkTo(body, king, m_goal, hero, heroAlive, val);
			}
		}

		private bool TrySlap(KitBody body, Vector2 king, Vector2 hero, bool heroAlive)
		{
			//IL_0012: 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_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//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)
			if (heroAlive && !(((KitBoss)this).UnpausedTime < m_nextSlap))
			{
				Vector2 val = hero - king;
				if (!(((Vector2)(ref val)).magnitude > 24f))
				{
					body.Brain.Face(hero - king);
					if (body.Brain.RequestAttack(1))
					{
						m_nextSlap = ((KitBoss)this).UnpausedTime + 1.4f;
						m_slapCue = Sfx.Keep("GrukkSlap", ((Component)body).transform);
						return true;
					}
					return false;
				}
			}
			return false;
		}

		private void WalkTo(KitBody body, Vector2 king, Vector2 goal, Vector2 hero, bool heroAlive, Vector2 faceWhenThere)
		{
			//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_0007: 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)
			//IL_0027: 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_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: 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_003a: 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_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: 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_007a: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val = goal - king;
			if (((Vector2)(ref val)).magnitude < 2f)
			{
				body.Brain.Stop();
				body.Brain.Face(faceWhenThere - king);
				return;
			}
			Vector2 dir;
			if (!heroAlive)
			{
				val = goal - king;
				dir = ((Vector2)(ref val)).normalized;
			}
			else
			{
				dir = Planner.Steer(king, goal, hero);
			}
			Vector2 val2 = Planner.Guard(king, dir);
			if (((Vector2)(ref val2)).sqrMagnitude < 0.0001f)
			{
				body.Brain.Stop();
			}
			else
			{
				body.Brain.SetMove(val2, 1f);
			}
		}

		private void Deny(KitBody body)
		{
			Sfx.Play("GrukkStepDenied", ((Component)body).transform);
			m_passDenied = true;
			m_deniedUntil = ((KitBoss)this).UnpausedTime + 1.5f;
			body.Brain.Stop();
			if ((Object)(object)Templates.DenyShake != (Object)null)
			{
				CutWindups();
				body.PlayStatus(Templates.DenyShake);
			}
			SetKing(King.Denied);
			KitSelfTest.Note("pass denied in phase " + ((KitBoss)this).Phase);
		}

		private void UpdateDenied(KitBody body, Vector2 king, Vector2 hero, bool heroAlive, float dt)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			if (!CommonFoot(dt))
			{
				if (heroAlive)
				{
					body.Brain.Face(hero - king);
				}
				if (m_kingTime >= 0.6f)
				{
					EndDenyShake(body);
					m_nextPlan = 0f;
					SetKing(King.Walking);
				}
			}
		}

		private static void EndDenyShake(KitBody body)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Invalid comparison between Unknown and I4
			if ((Object)(object)Templates.DenyShake != (Object)null && (int)body.Player.GetState() == 15 && (Object)(object)body.Anim != (Object)null && body.Anim.IsPlaying(((Object)Templates.DenyShake).name))
			{
				body.EndAction();
			}
		}

		internal void OnHookCatch(GrukkHook hook)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: 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_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: 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_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			KitBody lifeBody = ((KitBoss)this).LifeBody;
			if (!CanBeHooked || (Object)(object)lifeBody == (Object)null || !lifeBody.Alive)
			{
				if ((Object)(object)hook != (Object)null)
				{
					hook.Release();
				}
				return;
			}
			m_hook = hook;
			m_towLeft = 30f;
			Vector2 kingLocal = KingLocal;
			Vector2 val = Tuning.Gallows - kingLocal;
			m_towDir = ((((Vector2)(ref val)).sqrMagnitude > 0.01f) ? ((Vector2)(ref val)).normalized : Vector2.left);
			lifeBody.Brain.Stop();
			CutWindups();
			lifeBody.PlayStatus(Templates.Body["GrukkTowed"]);
			lifeBody.Brain.Face(m_towDir);
			m_nextPlan = 0f;
			RefreshGoal(TowEnd(kingLocal), m_towLeft / 60f);
			SetKing(King.Towed);
			KitSelfTest.Note("gallows: Grukk hooked and towed in phase " + ((KitBoss)this).Phase);
		}

		private Vector3 TowStep(Vector2 pos, float dt)
		{
			//IL_001b: 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_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_002d: 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_003a: 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_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: 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_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_00c3: Unknown result type (might be due to invalid IL or missing references)
			if (m_towLeft <= 0f)
			{
				return Vector3.zero;
			}
			float num = 60f * dt;
			Vector2 val = pos + m_towDir * num;
			bool flag = false;
			if (HeroLocal(out var p))
			{
				Vector2 val2 = val - p;
				float magnitude = ((Vector2)(ref val2)).magnitude;
				int num2;
				if (magnitude < 14f)
				{
					val2 = pos - p;
					num2 = ((magnitude < ((Vector2)(ref val2)).magnitude) ? 1 : 0);
				}
				else
				{
					num2 = 0;
				}
				flag = (byte)num2 != 0;
			}
			if (flag || ArenaPoly.EdgeDist(val) < 16f)
			{
				m_towLeft = 0f;
				return Vector3.zero;
			}
			m_towLeft -= num;
			return new Vector3(m_towDir.x * 60f, m_towDir.y * 60f, 0f);
		}

		private void UpdateTowed(KitBody body, Vector2 king, Vector2 hero, bool heroAlive, float dt)
		{
			//IL_000f: 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_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: 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_0082: Unknown result type (might be due to invalid IL or missing references)
			if (!CommonFoot(dt))
			{
				if (heroAlive && ArenaPoly.SegDist(hero + new Vector2(0f, 8f), Tuning.Pulley, king + new Vector2(0f, 10f)) <= 8f)
				{
					Sfx.Play("GrukkHookSnap", ((Component)body).transform);
					KitSelfTest.Note("gallows: the line snapped on the hero during the tow");
					EndTow();
				}
				else if (m_towLeft <= 0f)
				{
					EndTow();
				}
				else
				{
					RefreshGoal(TowEnd(king), m_towLeft / 60f);
				}
			}
		}

		private Vector2 TowEnd(Vector2 king)
		{
			//IL_002a: 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_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_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Max(0f, m_towLeft);
			if (HeroLocal(out var p))
			{
				num = Mathf.Min(num, TowRoomBeforeHero(king, p));
			}
			return ArenaPoly.ClampToward(king + m_towDir * num, king, 16f);
		}

		private float TowRoomBeforeHero(Vector2 king, Vector2 hero)
		{
			//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_0007: 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_000a: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val = hero - king;
			float num = Vector2.Dot(val, m_towDir);
			if (num <= 0f)
			{
				return float.MaxValue;
			}
			float num2 = ((Vector2)(ref val)).sqrMagnitude - num * num;
			float num3 = 196f;
			if (num2 >= num3)
			{
				return float.MaxValue;
			}
			return Mathf.Max(0f, num - Mathf.Sqrt(num3 - num2));
		}

		private void EndTow()
		{
			if (m_king == King.Towed)
			{
				if ((Object)(object)((KitBoss)this).LifeBody != (Object)null && ((KitBoss)this).LifeBody.Alive)
				{
					((KitBoss)this).LifeBody.EndAction();
				}
				m_nextPlan = 0f;
				SetKing(King.Walking);
			}
			if ((Object)(object)m_hook != (Object)null)
			{
				m_hook.Release();
				m_hook = null;
			}
		}

		private void StartClimb(bool barge)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			KitBody lifeBody = ((KitBoss)this).LifeBody;
			SetBarging(lifeBody, on: false);
			lifeBody.Brain.Stop();
			CutWindups();
			lifeBody.PlayCutscene(Templates.Body["GrukkClimb"], true);
			m_climbFrom = KingLocal;
			m_climbClock = 0f;
			SetKing(King.Climb);
			if (barge)
			{
				KitSelfTest.Note("barged aboard (" + (m_beat ? "beat" : "failsafe") + ")");
			}
		}

		private void UpdateClimb(KitBody body)
		{
			if (m_climbClock < 0.5f)
			{
				return;
			}
			Forms.Seated(body);
			body.EndAction();
			m_cart.ShowEmpty = false;
			m_cart.Snuff(FuseState.Fresh, 1.5f);
			m_seatClip = Templates.Body["GrukkSeatRoll"];
			Sfx.Play("GrukkCackle", ((Component)body).transform);
			m_armedAt = ((KitBoss)this).UnpausedTime + 0.5f;
			m_nextLob = Mathf.Max(m_nextLob, m_armedAt);
			m_nextSwat = Mathf.Max(m_nextSwat, m_armedAt);
			if (m_beat)
			{
				m_beat = false;
				if ((Object)(object)((KitBoss)this).LifeHealth != (Object)null)
				{
					((KitBoss)this).LifeHealth.StopInvincibility("Beat");
				}
				KitSelfTest.Note("phase " + ((KitBoss)this).Phase + " begins seated");
			}
			if (m_cart.Sim.Mode == CartMode.Halted || m_cart.Sim.Mode == CartMode.Fetch)
			{
				m_cart.Sim.Mode = CartMode.Cruise;
			}
			SetKing(King.Seated);
			KitSelfTest.Note("remounted in phase " + ((KitBoss)this).Phase);
		}

		private void StartFailsafe()
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Invalid comparison between Unknown and I4
			KitBody lifeBody = ((KitBoss)this).LifeBody;
			if ((Object)(object)m_hook != (Object)null)
			{
				m_hook.Release();
				m_hook = null;
			}
			if ((int)lifeBody.Player.GetState() == 15)
			{
				lifeBody.EndAction();
			}
			Sfx.Play("GrukkWhistle", ((Component)lifeBody).transform);
			lifeBody.Brain.Stop();
			CutWindups();
			lifeBody.PlayStatus(Templates.Body["GrukkWhistle"]);
			m_whistleUntil = ((KitBoss)this).UnpausedTime + Templates.Body.Length("GrukkWhistle");
			BeginFetch();
			SetKing(King.Failsafe);
			KitSelfTest.Note("on-foot limit ran out in phase " + ((KitBoss)this).Phase + ": failsafe");
		}

		private void BeginFetch()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			float num = CruiseFor(((KitBoss)this).Phase) * 1.6f;
			m_remountS = Planner.RemountPoint(KingLocal, m_cart.Sim, num);
			m_cart.Sim.HaltAt(m_remountS, num);
			m_remountStart = ((KitBoss)this).UnpausedTime;
		}

		private void StartBeat(int phase)
		{
			KitBody lifeBody = ((KitBoss)this).LifeBody;
			m_pendingBeat = false;
			m_beat = true;
			m_beatPhase = phase;
			if ((Object)(object)((KitBoss)this).LifeHealth != (Object)null)
			{
				((KitBoss)this).LifeHealth.StartInvincibility("Beat");
			}
			EndTow();
			SetBarging(lifeBody, on: false);
			lifeBody.Brain.Stop();
			CutWindups();
			lifeBody.HoldCutscene(Templates.Body["GrukkTantrum"], 2.25f, false);
			Sfx.Play("GrukkTantrum", ((Component)lifeBody).transform);
			m_beatStep = 0;
			m_beatWhistled = false;
			m_beatFetched = false;
			m_throws.Clear();
			SetKing(King.Beat);
			KitSelfTest.Note("phase " + phase + " beat: tantrum");
		}

		private void UpdateRemount(KitBody body, Vector2 king, Vector2 hero, bool heroAlive)
		{
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Invalid comparison between Unknown and I4
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Invalid comparison between Unknown and I4
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Invalid comparison between Unknown and I4
			//IL_0208: 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_020a: 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: Invalid comparison between Unknown and I4
			//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fb: 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)
			if (m_king == King.Beat && m_beatStep == 0)
			{
				exSpriteAnimClip val = Templates.Body["GrukkTantrum"];
				if (!m_beatWhistled && m_kingTime >= val.length - val.length / (float)Mathf.Max(1, val.frameInfos.Count))
				{
					m_beatWhistled = true;
					Sfx.Play("GrukkWhistle", ((Component)body).transform);
				}
				if (m_kingTime >= val.length)
				{
					if (!m_beatFetched)
					{
						m_beatFetched = true;
						BeginFetch();
					}
					if (!ThrowsOut() || !(m_kingTime < 2.25f) || (int)body.Player.GetState() != 13)
					{
						body.EndAction();
						m_beatStep = 1;
					}
				}
				return;
			}
			if (m_king == King.Failsafe)
			{
				if (((KitBoss)this).UnpausedTime < m_whistleUntil)
				{
					body.Brain.Stop();
					return;
				}
				if ((int)body.Player.GetState() == 15)
				{
					body.EndAction();
				}
			}
			if (m_cart.Sim.Mode == CartMode.Halted && m_beat && m_beatPhase >= 3 && m_cart.Sim.Dir != -1)
			{
				m_cart.Sim.Dir = -1;
			}
			Vector2 val2 = RailLine.Seat(m_remountS);
			bool flag = m_cart.Sim.Mode == CartMode.Halted;
			if (flag)
			{
				Vector2 val3 = val2 - king;
				if (((Vector2)(ref val3)).magnitude <= 6f || ((KitBoss)this).UnpausedTime - m_remountStart > 6f)
				{
					SetBarging(body, on: false);
					StartClimb(barge: true);
					return;
				}
			}
			SetBarging(body, flag);
			if (m_cart.Sim.Mode != CartMode.Fetch && m_cart.Sim.Mode != CartMode.Halted)
			{
				BeginFetch();
			}
			ePlayerState state = body.Player.GetState();
			if (((int)state == 2 || (int)state == 3) && (m_king != King.Failsafe || flag || !TrySlap(body, king, hero, heroAlive)))
			{
				WalkTo(body, king, val2, hero, heroAlive && !flag, RailLine.At(m_cart.Sim.S));
			}
		}

		private void SetBarging(KitBody body, bool on)
		{
			if (m_barging != on && !((Object)(object)body == (Object)null))
			{
				m_barging = on;
				Collider component = ((Component)body).GetComponent<Collider>();
				if ((Object)(object)component != (Object)null)
				{
					component.enabled = !on;
				}
			}
		}

		private bool ThrowsOut()
		{
			for (int i = 0; i < m_throws.Count; i++)
			{
				GrukkThrown grukkThrown = m_throws[i];
				if ((Object)(object)grukkThrown != (Object)null && !grukkThrown.Done && ((Component)grukkThrown).gameObject.activeInHierarchy)
				{
					return true;
				}
			}
			return false;
		}

		internal void OnEvThrow(bool crown)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: 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)
			//IL_0088: 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_0094: 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)
			try
			{
				if (m_king == King.Beat && m_beatStep == 0 && !((Object)(object)((KitBoss)this).LifeBody == (Object)null) && HeroLocal(out var p))
				{
					Vector2 val = KingLocal + new Vector2(0f, 12f);
					GameObject fx = Fx.SpawnOwned(crown ? Templates.CrownFx : Templates.ScepterFx, ((KitBoss)this).World(val), 0f, ((Component)((KitBoss)this).LifeBody).gameObject);
					GrukkThrown grukkThrown = GrukkThrown.Launch(((KitBoss)this).Arena, fx, val, p + new Vector2(0f, 8f), crown, () => KingLocal + new Vector2(0f, 34f));
					if ((Object)(object)grukkThrown != (Object)null)
					{
						m_throws.Add(grukkThrown);
					}
					Sfx.Play(crown ? "GrukkThrowCrown" : "GrukkThrowScepter", ((Component)((KitBoss)this).LifeBody).transform);
				}
			}
			catch (Exception ex)
			{
				((KitBoss)this).Ctx.Log.WarnOnce("grukk throw event", ex);
			}
		}

		private void BuildStations(Room room)
		{
			//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_001c: 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_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: 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_006e: Expected O, but got Unknown
			//IL_0091: 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_00a6: 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_00b5: 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_00cb: 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_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Expected O, but got Unknown
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: 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_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Expected O, but got Unknown
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f4: Expected O, but got Unknown
			//IL_021f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0224: Unknown result type (might be due to invalid IL or missing references)
			//IL_0229: Unknown result type (might be due to invalid IL or missing references)
			//IL_0240: 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)
			m_towerA = ((KitBoss)this).SpawnStation(Templates.TowerA, Tuning.TowerA, new StationSpec
			{
				Kind = "TowerA",
				DrawnSeatLocal = Tuning.TowerASeat,
				LineOfSight = false,
				CanHit = (KitStation st, Player hero) => TowerCanHit(0),
				ShouldEnter = TowerShouldEnter,
				ShouldExit = TowerShouldExit
			});
			m_towerA.Fired += delegate
			{
				OnTowerFired(0);
			};
			m_towerB = ((KitBoss)this).SpawnStation(Templates.TowerB, Tuning.TowerB, new StationSpec
			{
				Kind = "TowerB",
				WakePhase = 2,
				DimWhenDormant = false,
				DrawnSeatLocal = Tuning.TowerBSeat,
				LineOfSight = false,
				CanHit = (KitStation st, Player hero) => TowerCanHit(1),
				ShouldEnter = TowerShouldEnter,
				ShouldExit = TowerShouldExit
			});
			m_towerB.Fired += delegate
			{
				OnTowerFired(1);
			};
			m_brake = ((KitBoss)this).SpawnStation(Templates.Brake, Tuning.Brake, new StationSpec
			{
				Kind = "Brake",
				DrawnSeatLocal = Tuning.BrakeSeat,
				LineOfSight = false,
				CanHit = (KitStation st, Player hero) => BrakeCanHit(),
				ShouldEnter = BrakeShouldEnter,
				ShouldExit = BrakeShouldExit
			});
			m_brake.Fired += delegate
			{
				OnBrakeFired();
			};
			m_gallows = ((KitBoss)this).SpawnStation(Templates.Gallows, Tuning.Gallows, new StationSpec
			{
				Kind = "Gallows",
				HumanOnly = true,
				DrawnSeatLocal = Tuning.GallowsSeat,
				AimInitial = 0f
			});
			m_gallows.Fired += delegate
			{
				OnGallowsFired();
			};
			m_wantGrey = true;
			m_gaugeA = Gauge(m_towerA, Tuning.TowerA + Tuning.TowerAGauge);
			m_gaugeB = Gauge(m_towerB, Tuning.TowerB + Tuning.TowerBGauge);
			m_brake.SetSuspended(true);
			m_gallows.SetSuspended(true);
		}

		private void UpdateDormantLook()
		{
			if (m_wantGrey && ++m_lateFrames >= 2)
			{
				m_wantGrey = false;
				if ((Object)(object)m_towerB != (Object)null && m_towerB.Dormant)
				{
					DormantLook(m_towerB, grey: true);
				}
			}
		}

		private void DormantLook(KitStation st, bool grey)
		{
			if ((Object)(object)st == (Object)null || (Object)(object)st.States == (Object)null)
			{
				return;
			}
			try
			{
				exSpriteAnimation component = ((Component)st).GetComponent<exSpriteAnimation>();
				if (grey)
				{
					((Behaviour)st.States).enabled = false;
					if ((Object)(object)component != (Object)null)
					{
						component.Play(Templates.Env["GrukkTowerB_greyedOut"]);
					}
					m_towerBGrey = true;
				}
				else if (m_towerBGrey)
				{
					m_towerBGrey = false;
					((Behaviour)st.States).enabled = true;
					st.States.SetState("Inactive");
				}
			}
			catch (Exception ex)
			{
				((KitBoss)this).Ctx.Log.WarnOnce("tower B dormant look", ex);
			}
		}

		private exSprite Gauge(KitStation st, Vector2 local)
		{
			//IL_0022: 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)
			if ((Object)(object)st == (Object)null)
			{
				return null;
			}
			return KitArt.CreateSprite(((Component)st).transform, Templates.Env.Sheet, "GrukkTowerGauge", 4, ((KitBoss)this).World(local), (Anchor)7, false, 0f);
		}

		private TowerView ViewOf(int i)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			KitStation val = ((i == 0) ? m_towerA : m_towerB);
			TowerView result = new TowerView
			{
				Pour = ((i == 0) ? Tuning.TowerA : Tuning.TowerB),
				PourAge = ((KitBoss)this).UnpausedTime - m_pourStart[i],
				CartClear = ((i == 0) ? 6f : 2.3f)
			};
			if ((Object)(object)val != (Object)null && (Object)(object)val.Trap != (Object)null)
			{
				result.Full = val.Trap.GetCooldown() <= 0f;
				result.Awake = !val.Dormant && !val.Suspended && !val.Retired;
			}
			return result;
		}

		internal int TowerDousingAt(Vector2 sparkLocal)
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < 2; i++)
			{
				KitStation val = ((i == 0) ? m_towerA : m_towerB);
				if (!((Object)(object)val == (Object)null) && !val.Dormant && !val.Retired)
				{
					TowerView towerView = ViewOf(i);
					if (towerView.Dousing && towerView.InPatch(sparkLocal, 0f))
					{
						return i;
					}
				}
			}
			return -1;
		}

		private bool TowerCanHit(int i)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if ((Object)(object)m_cart == (Object)null || !((KitBoss)this).Fighting || !HeroLocal(out var p))
				{
					return false;
				}
				return BotRules.TowerShouldPour(ViewOf(i), m_cart.Sim, m_cart.Fuse, p, (m_brakeBiteAt > 0f) ? Mathf.Max(0f, m_brakeBiteAt - ((KitBoss)this).UnpausedTime) : (-1f));
			}
			catch (Exception ex)
			{
				((KitBoss)this).Ctx.Log.WarnOnce("tower can hit", ex);
				return false;
			}
		}

		private bool TowerShouldEnter(KitStation st, Player hero)
		{
			if ((Object)(object)st.Trap != (Object)null && st.Trap.GetCooldown() <= 0f && !st.Suspended && !st.Dormant)
			{
				return ((KitBoss)this).Fighting;
			}
			return false;
		}

		private bool TowerShouldExit(KitStation st, Player hero)
		{
			if (!((Object)(object)st.Trap == (Object)null))
			{
				return st.Trap.GetCooldown() > 0f;
			}
			return true;
		}

		private void OnTowerFired(int i)
		{
			m_pourStart[i] = ((KitBoss)this).UnpausedTime;
			KitStation val = ((i == 0) ? m_towerA : m_towerB);
			m_delugeSoundAt[i] = ((KitBoss)this).UnpausedTime + 0.5f - 0.03f;
			if (i == 1)
			{
				m_towerBDeep = true;
			}
			PlayerData val2 = (((Object)(object)val != (Object)null) ? val.Occupant : null);
			KitSelfTest.Note("tower " + ((i == 0) ? "A" : "B") + " poured (" + ((val2 == null) ? "?" : (val2.IsBot ? "bot" : "human")) + ", fuse " + (((Object)(object)m_cart != (Object)null) ? m_cart.Fuse.State.ToString() : "?") + ")");
		}

		private void UpdateDelugeSounds()
		{
			for (int i = 0; i < 2; i++)
			{
				if (m_delugeSoundAt[i] > 0f && ((KitBoss)this).UnpausedTime >= m_delugeSoundAt[i])
				{
					m_delugeSoundAt[i] = -1f;
					KitStation val = ((i == 0) ? m_towerA : m_towerB);
					if ((Object)(object)val != (Object)null && (Object)(object)val.States != (Object)null && ((Behaviour)val.States).enabled && val.States.GetStateName() == "Action")
					{
						Sfx.Play("GrukkDeluge", ((Component)val).transform);
					}
				}
			}
		}

		private bool BrakeCanHit()
		{
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if ((Object)(object)m_cart == (Object)null || !((KitBoss)this).Fighting || (Object)(object)m_brake == (Object)null || m_brake.Suspended)
				{
					return false;
				}
				s_towers[0] = ViewOf(0);
				s_towers[1] = ViewOf(1);
				bool num = BotRules.BrakeShouldRing(s_towers, m_cart.Sim, m_cart.Fuse, KingOnFootForBots, KingLocal);
				if (num)
				{
					m_brakeLastWanted = ((KitBoss)this).UnpausedTime;
				}
				return num;
			}
			catch (Exception ex)
			{
				((KitBoss)this).Ctx.Log.WarnOnce("brake can hit", ex);
				return false;
			}
		}

		private bool BrakeProspect()
		{
			if ((Object)(object)m_cart == (Object)null || !((KitBoss)this).Fighting || (Object)(object)m_brake == (Object)null || m_brake.Suspended || m_beat)
			{
				return false;
			}
			if (KingOnFootForBots)
			{
				return true;
			}
			if (m_king != King.Seated || m_cart.Fuse.State == FuseState.Spent)
			{
				return false;
			}
			TowerView towerView = ViewOf(0);
			TowerView towerView2 = ViewOf(1);
			if (!towerView.Full || !towerView.Awake)
			{
				if (towerView2.Full)
				{
					return towerView2.Awake;
				}
				return false;
			}
			return true;
		}

		private bool BrakeShouldEnter(KitStation st, Player hero)
		{
			if (!st.Suspended)
			{
				return BrakeProspect();
			}
			return false;
		}

		private bool BrakeShouldExit(KitStation st, Player hero)
		{
			if (!((Object)(object)st.Trap == (Object)null) && !(st.Trap.GetCooldown() > 0f))
			{
				return ((KitBoss)this).UnpausedTime - m_brakeLastWanted > 3f;
			}
			return true;
		}

		private void UpdateBrakeIdle()
		{
			if ((Object)(object)m_brake != (Object)null && (m_brake.Occupant == null || BrakeProspect()))
			{
				m_brakeLastWanted = ((KitBoss)this).UnpausedTime;
			}
		}

		private void OnBrakeFired()
		{
			Sfx.Play("GrukkBrakeBell", ((Component)m_brake).transform);
			m_brakeBiteAt = ((KitBoss)this).UnpausedTime + 0.4f;
		}

		private void OnGallowsFired()
		{
			m_gallowsFireAt = ((KitBoss)this).UnpausedTime + 0.2f;
		}

		private void UpdateTimedPresses(Vector2 king)
		{
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: 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_0080: Invalid comparison between Unknown and I4
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Invalid comparison between Unknown and I4
			if (m_brakeBiteAt > 0f && ((KitBoss)this).UnpausedTime >= m_brakeBiteAt)
			{
				m_brakeBiteAt = -1f;
				if (m_cart.Sim.StartBrake())
				{
					Sfx.Play("GrukkBrakeSkid", ((Component)m_cart).transform);
					if (m_king == King.Seated && (Object)(object)((KitBoss)this).LifeBody != (Object)null)
					{
						ePlayerState state = ((KitBoss)this).LifeBody.Player.GetState();
						if ((int)state == 2 || (int)state == 3)
						{
							((KitBoss)this).LifeBody.PlayStatus(Templates.Body["GrukkLurch"]);
						}
					}
					KitSelfTest.Note("brake bit (fuse " + m_cart.Fuse.State.ToString() + ", king " + m_king.ToString() + ")");
				}
				else if ((Object)(object)m_brake != (Object)null)
				{
					m_brake.RefundCooldown();
				}
			}
			if (m_gallowsFireAt > 0f && ((KitBoss)this).UnpausedTime >= m_gallowsFireAt)
			{
				m_gallowsFireAt = -1f;
				if (CanBeHooked && (Object)(object)m_gallows !