Decompiled source of Scp173 v1.1.0

SCP173.dll

Decompiled a week 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 DM;
using HarmonyLib;
using Landfall.TABS;
using Landfall.TABS.AI;
using Landfall.TABS.AI.Components.Modifiers;
using Landfall.TABS.AI.Components.Tags;
using Landfall.TABS.AI.Systems;
using Landfall.TABS.GameMode;
using Landfall.TABS.Services;
using Landfall.TABS.UnitPlacement;
using Landfall.TABS.WinConditions;
using Landfall.TABS.Workshop;
using Microsoft.CodeAnalysis;
using Unity.Entities;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyVersion("0.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 SCP173Mod
{
	public static class DummyUnitFactory
	{
		public const string FactionName = "Scp-173";

		public const string UnitName = "SCP-173";

		private static readonly FieldInfo s_unitBlueprintEntityField = typeof(UnitBlueprint).GetField("m_entity", BindingFlags.Instance | BindingFlags.NonPublic);

		public static Faction BuiltFaction { get; private set; }

		public static UnitBlueprint BuiltBlueprint { get; private set; }

		public static void BuildAndRegister()
		{
			//IL_002f: 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)
			ContentDatabase val = ContentDatabase.Instance();
			if (val == null)
			{
				return;
			}
			if ((Object)(object)BuiltFaction != (Object)null && (Object)(object)BuiltBlueprint != (Object)null)
			{
				Faction faction = val.GetFaction(BuiltFaction.Entity.GUID);
				UnitBlueprint unitBlueprint = val.GetUnitBlueprint(BuiltBlueprint.Entity.GUID);
				if (!((Object)(object)faction == (Object)(object)BuiltFaction) || !((Object)(object)unitBlueprint == (Object)(object)BuiltBlueprint))
				{
					if ((Object)(object)unitBlueprint == (Object)null)
					{
						val.AddUserUnitBlueprint(BuiltBlueprint);
					}
					if ((Object)(object)faction == (Object)null)
					{
						val.AddUserFaction(BuiltFaction);
					}
				}
			}
			else
			{
				GameObject val2 = FindTemplateUnitBase();
				if (!((Object)(object)val2 == (Object)null))
				{
					BuiltBlueprint = CreateBlueprint(val2);
					BuiltFaction = CreateFaction(BuiltBlueprint);
					val.AddUserUnitBlueprint(BuiltBlueprint);
					val.AddUserFaction(BuiltFaction);
				}
			}
		}

		public static bool IsDummy(Unit unit)
		{
			if ((Object)(object)unit != (Object)null && (Object)(object)BuiltBlueprint != (Object)null)
			{
				return unit.unitBlueprint == BuiltBlueprint;
			}
			return false;
		}

		private static GameObject FindTemplateUnitBase()
		{
			ContentDatabase val = ContentDatabase.Instance();
			string[] array = new string[4] { "Farmer", "Peasant", "Peon", "Warrior" };
			foreach (string name in array)
			{
				UnitBlueprint val2 = val.GetAllFactions().SelectMany((Faction f) => f.Units).FirstOrDefault((Func<UnitBlueprint, bool>)((UnitBlueprint u) => (Object)(object)u != (Object)null && u.Entity != null && u.Entity.Name == name));
				if ((Object)(object)val2 != (Object)null && (Object)(object)val2.UnitBase != (Object)null)
				{
					return val2.UnitBase;
				}
			}
			UnitBlueprint val3 = (from f in val.GetAllFactions()
				where !f.IsSecret
				select f).SelectMany((Faction f) => f.Units).FirstOrDefault((Func<UnitBlueprint, bool>)((UnitBlueprint u) => (Object)(object)u != (Object)null && (Object)(object)u.UnitBase != (Object)null && !u.HasMissingComponents));
			if (!((Object)(object)val3 != (Object)null))
			{
				return null;
			}
			return val3.UnitBase;
		}

		private static void InitUnitBlueprintEntity(UnitBlueprint bp, string entityName)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			DatabaseEntity val = new DatabaseEntity((WorkshopContentType)0);
			val.Name = entityName;
			s_unitBlueprintEntityField.SetValue(bp, val);
		}

		private static UnitBlueprint CreateBlueprint(GameObject templateUnitBase)
		{
			//IL_0065: 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_007e: 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)
			UnitBlueprint val = ScriptableObject.CreateInstance<UnitBlueprint>();
			((Object)val).name = "SCP-173";
			InitUnitBlueprintEntity(val, "SCP-173");
			GameObject val2 = CloneTemplateInactive(templateUnitBase);
			RemoveTeamColorComponents(val2);
			val.UnitBase = val2;
			val.RightWeapon = null;
			val.LeftWeapon = null;
			Unit component = val2.GetComponent<Unit>();
			if ((Object)(object)component != (Object)null)
			{
				component.unitBlueprint = val;
			}
			val.excludeFromWinCondition = true;
			val.MovementComponents = new List<IMovementComponent> { (IMovementComponent)(object)default(KeepPreferredDistance) };
			val.TargetingComponent = (ITargetingComponent)(object)default(EnemyLeastWeightTargeting);
			val.turnSpeed = 18f;
			val.turnSpeedCurve = AnimationCurve.Linear(0f, 1f, 1f, 1f);
			return val;
		}

		private static GameObject CloneTemplateInactive(GameObject template)
		{
			bool activeSelf = template.activeSelf;
			if (activeSelf)
			{
				template.SetActive(false);
			}
			GameObject obj = Object.Instantiate<GameObject>(template);
			((Object)obj).name = "SCP173_Dummy";
			obj.SetActive(false);
			Object.DontDestroyOnLoad((Object)(object)obj);
			if (activeSelf)
			{
				template.SetActive(true);
			}
			return obj;
		}

		private static void RemoveTeamColorComponents(GameObject root)
		{
			if ((Object)(object)root == (Object)null)
			{
				return;
			}
			TeamColor[] componentsInChildren = root.GetComponentsInChildren<TeamColor>(true);
			foreach (TeamColor val in componentsInChildren)
			{
				if ((Object)(object)val != (Object)null)
				{
					Object.DestroyImmediate((Object)(object)val);
				}
			}
		}

		private static void InitFactionEntity(Faction faction)
		{
			faction.Init();
			faction.Entity.Name = "Scp-173";
		}

		private static Faction CreateFaction(UnitBlueprint blueprint)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			Faction val = ScriptableObject.CreateInstance<Faction>();
			((Object)val).name = "Scp-173";
			InitFactionEntity(val);
			val.IsCustom = true;
			val.m_displayFaction = true;
			val.m_FactionCatagory = (FactionCatagory)1;
			val.Units = (UnitBlueprint[])(object)new UnitBlueprint[1] { blueprint };
			return val;
		}
	}
	internal static class EmbeddedAssetLoader
	{
		private static readonly Assembly ModAssembly = typeof(EmbeddedAssetLoader).Assembly;

		private static readonly object Gate = new object();

		private static string CacheRoot;

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

		private static Dictionary<string, string> ResourceMap;

		internal static void InitializeCache()
		{
			if (CacheRoot == null)
			{
				CacheRoot = Path.Combine(Path.GetTempPath(), "SCP173Mod_Embedded", "Assets");
				Directory.CreateDirectory(CacheRoot);
				BuildResourceMap();
			}
		}

		internal static byte[] LoadBytes(string fileName)
		{
			string text = FindResource(fileName);
			if (text == null)
			{
				return null;
			}
			using Stream stream = ModAssembly.GetManifestResourceStream(text);
			if (stream == null)
			{
				return null;
			}
			using MemoryStream memoryStream = new MemoryStream();
			stream.CopyTo(memoryStream);
			return memoryStream.ToArray();
		}

		internal static string LoadText(string fileName)
		{
			byte[] array = LoadBytes(fileName);
			if (array != null)
			{
				return Encoding.UTF8.GetString(array);
			}
			return null;
		}

		internal static bool ExtractAllEmbeddedAssets()
		{
			InitializeCache();
			bool result = true;
			string[] manifestResourceNames = ModAssembly.GetManifestResourceNames();
			foreach (string text in manifestResourceNames)
			{
				if (text.StartsWith("SCP173Mod.Assets.", StringComparison.OrdinalIgnoreCase))
				{
					string fileName = text.Substring("SCP173Mod.Assets.".Length);
					if (ExtractResource(text, fileName) == null)
					{
						result = false;
					}
				}
			}
			return result;
		}

		internal static string ExtractToTemp(string fileName)
		{
			InitializeCache();
			if (Extracted.TryGetValue(fileName, out var value) && File.Exists(value))
			{
				return value;
			}
			string text = FindResource(fileName);
			if (text == null)
			{
				return null;
			}
			return ExtractResource(text, Path.GetFileName(fileName));
		}

		internal static string GetCachedPath(string fileName)
		{
			return ExtractToTemp(fileName);
		}

		private static void BuildResourceMap()
		{
			lock (Gate)
			{
				if (ResourceMap == null)
				{
					ResourceMap = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
					string[] manifestResourceNames = ModAssembly.GetManifestResourceNames();
					for (int i = 0; i < manifestResourceNames.Length; i++)
					{
						string key = manifestResourceNames[i].Replace('/', '.').Replace('\\', '.');
						ResourceMap[key] = manifestResourceNames[i];
					}
				}
			}
		}

		private static string FindResource(string fileName)
		{
			InitializeCache();
			string text = fileName.Replace('\\', '.').Replace('/', '.');
			if (text.StartsWith(".", StringComparison.Ordinal))
			{
				text = text.TrimStart(new char[1] { '.' });
			}
			if (ResourceMap.TryGetValue(text, out var value))
			{
				return value;
			}
			string value2 = "." + text;
			foreach (KeyValuePair<string, string> item in ResourceMap)
			{
				if (item.Key.EndsWith(value2, StringComparison.OrdinalIgnoreCase))
				{
					return item.Value;
				}
			}
			return null;
		}

		private static string ExtractResource(string resourceName, string fileName)
		{
			try
			{
				string fileName2 = Path.GetFileName(fileName);
				string text = Path.Combine(CacheRoot, fileName2);
				using (Stream stream = ModAssembly.GetManifestResourceStream(resourceName))
				{
					if (stream == null)
					{
						return null;
					}
					using FileStream destination = new FileStream(text, FileMode.Create, FileAccess.Write, FileShare.Read);
					stream.CopyTo(destination);
				}
				Extracted[fileName] = text;
				return text;
			}
			catch
			{
				return null;
			}
		}
	}
	[HarmonyPatch(typeof(Unit), "Start")]
	public static class Unit_Start_Patch
	{
		[HarmonyPostfix]
		public static void Postfix(Unit __instance)
		{
			SCP173SpawnReplacer.ReplaceIfDummy(__instance);
			if ((Object)(object)__instance != (Object)null && !SCP173Runtime.IsReferenceProxy(__instance))
			{
				UnitRegistry.Register(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(Unit), "OnDestroy")]
	public static class Unit_OnDestroy_Patch
	{
		[HarmonyPostfix]
		public static void Postfix(Unit __instance)
		{
			if (!SCP173Runtime.IsReferenceProxy(__instance))
			{
				UnitRegistry.Unregister(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(CustomContentLoaderModIO), "DoneDownloading")]
	public static class CustomContentLoaderModIO_DoneDownloading_Patch
	{
		[HarmonyPostfix]
		public static void Postfix()
		{
			DummyUnitFactory.BuildAndRegister();
		}
	}
	[HarmonyPatch(typeof(UnitPlacementBrush), "PlaceUnitInternal")]
	public static class UnitPlacementBrush_PlaceUnitInternal_Patch
	{
		[HarmonyPrefix]
		public static bool Prefix(UnitBlueprint blueprint)
		{
			if ((Object)(object)blueprint == (Object)null || (Object)(object)DummyUnitFactory.BuiltBlueprint == (Object)null)
			{
				return true;
			}
			if (blueprint != DummyUnitFactory.BuiltBlueprint)
			{
				return true;
			}
			if (!SCP173Runtime.HasSpawned)
			{
				return !SCP173Runtime.SpawnInProgress;
			}
			return false;
		}
	}
	public static class SceneResetHook
	{
		public static void Install()
		{
			SceneManager.activeSceneChanged -= OnChanged;
			SceneManager.activeSceneChanged += OnChanged;
		}

		private static void OnChanged(Scene oldScene, Scene newScene)
		{
			SCP173Runtime.ResetSceneState();
		}
	}
	public static class NeckSnapDeformer
	{
		public static void SnapNeck(Unit victim, float angleDegrees)
		{
			//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_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_004c: 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_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_007b: 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_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			//IL_00ba: 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_00fe: 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_012a: 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_0137: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)victim == (Object)null || (Object)(object)victim.data == (Object)null)
			{
				return;
			}
			Transform head = victim.Head;
			Transform torso = victim.data.torso;
			if ((Object)(object)head == (Object)null || (Object)(object)torso == (Object)null)
			{
				return;
			}
			Vector3 right = torso.right;
			Quaternion val = Quaternion.AngleAxis(angleDegrees, right);
			head.rotation = val * head.rotation;
			Rigidbody component = ((Component)head).GetComponent<Rigidbody>();
			Rigidbody component2 = ((Component)torso).GetComponent<Rigidbody>();
			if ((Object)(object)component != (Object)null)
			{
				component.angularVelocity = right * (angleDegrees * ((float)Math.PI / 180f)) * 6f;
				if ((Object)(object)component2 != (Object)null)
				{
					Vector3 val2 = component2.position - component.position;
					component.AddForce(((Vector3)(ref val2)).normalized * 2.5f, (ForceMode)2);
				}
			}
			ConfigurableJoint val3 = ((Component)head).GetComponent<ConfigurableJoint>();
			if ((Object)(object)val3 == (Object)null && (Object)(object)torso != (Object)null)
			{
				val3 = ((Component)torso).GetComponentInChildren<ConfigurableJoint>();
			}
			if ((Object)(object)val3 != (Object)null)
			{
				JointDrive val4 = default(JointDrive);
				((JointDrive)(ref val4)).positionSpring = 0f;
				((JointDrive)(ref val4)).positionDamper = 0f;
				((JointDrive)(ref val4)).maximumForce = 0f;
				JointDrive angularYZDrive = (val3.angularXDrive = val4);
				val3.angularYZDrive = angularYZDrive;
			}
		}
	}
	public static class ObjRuntimeLoader
	{
		public static Mesh LoadMesh(string objPath)
		{
			//IL_0256: Unknown result type (might be due to invalid IL or missing references)
			//IL_025d: Expected O, but got Unknown
			//IL_00d5: 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_012e: Unknown result type (might be due to invalid IL or missing references)
			if (!File.Exists(objPath))
			{
				return null;
			}
			List<Vector3> list = new List<Vector3>();
			List<Vector2> list2 = new List<Vector2>();
			List<Vector3> list3 = new List<Vector3>();
			List<Vector3> list4 = new List<Vector3>();
			List<Vector2> list5 = new List<Vector2>();
			List<Vector3> list6 = new List<Vector3>();
			List<int> list7 = new List<int>();
			Dictionary<string, int> cache = new Dictionary<string, int>();
			CultureInfo invariantCulture = CultureInfo.InvariantCulture;
			foreach (string item in File.ReadLines(objPath))
			{
				if (string.IsNullOrEmpty(item))
				{
					continue;
				}
				string text = item.Trim();
				if (text.Length == 0 || text[0] == '#')
				{
					continue;
				}
				if (text.StartsWith("v "))
				{
					string[] array = SplitWhitespace(text.Substring(2));
					float num = float.Parse(array[0], invariantCulture);
					float num2 = float.Parse(array[1], invariantCulture);
					float num3 = float.Parse(array[2], invariantCulture);
					list.Add(new Vector3(num, num2, num3));
				}
				else if (text.StartsWith("vt "))
				{
					string[] array2 = SplitWhitespace(text.Substring(3));
					float num4 = float.Parse(array2[0], invariantCulture);
					float num5 = ((array2.Length > 1) ? float.Parse(array2[1], invariantCulture) : 0f);
					list2.Add(new Vector2(num4, num5));
				}
				else if (text.StartsWith("vn "))
				{
					string[] array3 = SplitWhitespace(text.Substring(3));
					float num6 = float.Parse(array3[0], invariantCulture);
					float num7 = float.Parse(array3[1], invariantCulture);
					float num8 = float.Parse(array3[2], invariantCulture);
					list3.Add(new Vector3(num6, num7, num8));
				}
				else
				{
					if (!text.StartsWith("f "))
					{
						continue;
					}
					string[] array4 = SplitWhitespace(text.Substring(2));
					if (array4.Length >= 3)
					{
						int[] array5 = new int[array4.Length];
						for (int i = 0; i < array4.Length; i++)
						{
							array5[i] = ResolveVertex(array4[i], list, list2, list3, list4, list5, list6, cache);
						}
						for (int j = 1; j < array5.Length - 1; j++)
						{
							list7.Add(array5[0]);
							list7.Add(array5[j]);
							list7.Add(array5[j + 1]);
						}
					}
				}
			}
			if (list4.Count == 0 || list7.Count == 0)
			{
				return null;
			}
			Mesh val = new Mesh();
			((Object)val).name = "SCP173_Mesh";
			val.indexFormat = (IndexFormat)(list4.Count > 65000);
			val.SetVertices(list4);
			if (list5.Count == list4.Count)
			{
				val.SetUVs(0, list5);
			}
			if (list6.Count == list4.Count)
			{
				val.SetNormals(list6);
			}
			val.SetTriangles(list7, 0);
			if (list6.Count != list4.Count)
			{
				val.RecalculateNormals();
			}
			val.RecalculateBounds();
			val.RecalculateTangents();
			return val;
		}

		private static int ResolveVertex(string token, List<Vector3> positions, List<Vector2> uvs, List<Vector3> normals, List<Vector3> finalVerts, List<Vector2> finalUVs, List<Vector3> finalNormals, Dictionary<string, int> cache)
		{
			//IL_007a: 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_008a: 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_00a4: Unknown result type (might be due to invalid IL or missing references)
			if (cache.TryGetValue(token, out var value))
			{
				return value;
			}
			string[] array = token.Split(new char[1] { '/' });
			int index = ParseIndex(array[0], positions.Count);
			int num = ((array.Length > 1 && array[1].Length > 0) ? ParseIndex(array[1], uvs.Count) : (-1));
			int num2 = ((array.Length > 2 && array[2].Length > 0) ? ParseIndex(array[2], normals.Count) : (-1));
			finalVerts.Add(positions[index]);
			finalUVs.Add((num >= 0) ? uvs[num] : Vector2.zero);
			finalNormals.Add((num2 >= 0) ? normals[num2] : Vector3.zero);
			return cache[token] = finalVerts.Count - 1;
		}

		private static int ParseIndex(string s, int count)
		{
			int num = int.Parse(s, CultureInfo.InvariantCulture);
			if (num > 0)
			{
				return num - 1;
			}
			return count + num;
		}

		private static string[] SplitWhitespace(string s)
		{
			return s.Split(new char[2] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
		}

		public static Mesh LoadMeshFromText(string objText)
		{
			//IL_00b5: 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_0232: Expected O, but got Unknown
			//IL_0154: 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)
			if (string.IsNullOrEmpty(objText))
			{
				return null;
			}
			List<Vector3> list = new List<Vector3>();
			List<Vector2> list2 = new List<Vector2>();
			List<Vector3> list3 = new List<Vector3>();
			List<Vector3> list4 = new List<Vector3>();
			List<Vector2> list5 = new List<Vector2>();
			List<Vector3> list6 = new List<Vector3>();
			List<int> list7 = new List<int>();
			Dictionary<string, int> cache = new Dictionary<string, int>();
			CultureInfo invariantCulture = CultureInfo.InvariantCulture;
			using (StringReader stringReader = new StringReader(objText))
			{
				string text;
				while ((text = stringReader.ReadLine()) != null)
				{
					string text2 = text.Trim();
					if (text2.Length == 0 || text2[0] == '#')
					{
						continue;
					}
					if (text2.StartsWith("v "))
					{
						string[] array = SplitWhitespace(text2.Substring(2));
						list.Add(new Vector3(float.Parse(array[0], invariantCulture), float.Parse(array[1], invariantCulture), float.Parse(array[2], invariantCulture)));
					}
					else if (text2.StartsWith("vt "))
					{
						string[] array2 = SplitWhitespace(text2.Substring(3));
						list2.Add(new Vector2(float.Parse(array2[0], invariantCulture), (array2.Length > 1) ? float.Parse(array2[1], invariantCulture) : 0f));
					}
					else if (text2.StartsWith("vn "))
					{
						string[] array3 = SplitWhitespace(text2.Substring(3));
						list3.Add(new Vector3(float.Parse(array3[0], invariantCulture), float.Parse(array3[1], invariantCulture), float.Parse(array3[2], invariantCulture)));
					}
					else
					{
						if (!text2.StartsWith("f "))
						{
							continue;
						}
						string[] array4 = SplitWhitespace(text2.Substring(2));
						if (array4.Length >= 3)
						{
							int[] array5 = new int[array4.Length];
							for (int i = 0; i < array4.Length; i++)
							{
								array5[i] = ResolveVertex(array4[i], list, list2, list3, list4, list5, list6, cache);
							}
							for (int j = 1; j < array5.Length - 1; j++)
							{
								list7.Add(array5[0]);
								list7.Add(array5[j]);
								list7.Add(array5[j + 1]);
							}
						}
					}
				}
			}
			if (list4.Count == 0 || list7.Count == 0)
			{
				return null;
			}
			Mesh val = new Mesh();
			((Object)val).name = "SCP173_Mesh";
			val.indexFormat = (IndexFormat)(list4.Count > 65000);
			val.SetVertices(list4);
			if (list5.Count == list4.Count)
			{
				val.SetUVs(0, list5);
			}
			if (list6.Count == list4.Count)
			{
				val.SetNormals(list6);
			}
			else
			{
				val.RecalculateNormals();
			}
			val.SetTriangles(list7, 0);
			val.RecalculateBounds();
			val.RecalculateTangents();
			return val;
		}

		public static Texture2D LoadTextureBytes(byte[] bytes, string name)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected O, but got Unknown
			if (bytes == null || bytes.Length == 0)
			{
				return null;
			}
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, true);
			if (!ImageConversion.LoadImage(val, bytes))
			{
				return null;
			}
			((Object)val).name = name;
			((Texture)val).wrapMode = (TextureWrapMode)0;
			val.Apply(true, false);
			return val;
		}

		public static Texture2D LoadTexture(string path)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			if (!File.Exists(path))
			{
				return null;
			}
			byte[] array = File.ReadAllBytes(path);
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, true);
			if (!ImageConversion.LoadImage(val, array))
			{
				return null;
			}
			((Object)val).name = Path.GetFileNameWithoutExtension(path);
			((Texture)val).wrapMode = (TextureWrapMode)0;
			val.Apply(true, false);
			return val;
		}
	}
	[BepInPlugin("belpinex.tabs.scp173", "SCP-173 (Faccion Custom)", "1.1.4")]
	public class Plugin : BaseUnityPlugin
	{
		private Harmony m_harmony;

		private void Awake()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			m_harmony = new Harmony("belpinex.tabs.scp173");
			m_harmony.PatchAll();
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
			EmbeddedAssetLoader.ExtractAllEmbeddedAssets();
			SCP173Audio.EnsureLoaded();
			((MonoBehaviour)this).StartCoroutine(DelayedVisualAssetWarmup());
			SceneResetHook.Install();
			((MonoBehaviour)this).StartCoroutine(WaitForContentDatabaseThenRegister());
		}

		private IEnumerator DelayedVisualAssetWarmup()
		{
			yield return null;
			SCP173SpawnReplacer.PreloadAssets();
		}

		private IEnumerator WaitForContentDatabaseThenRegister()
		{
			float elapsed = 0f;
			while (elapsed < 60f)
			{
				ContentDatabase val;
				try
				{
					val = ContentDatabase.Instance();
				}
				catch
				{
					val = null;
				}
				if (val != null && val.GetAllFactions() != null && val.GetAllFactions().Any())
				{
					break;
				}
				elapsed += Time.unscaledDeltaTime;
				yield return null;
			}
			if (!(elapsed >= 60f))
			{
				DummyUnitFactory.BuildAndRegister();
			}
		}
	}
	public sealed class SCP173Audio : MonoBehaviour
	{
		private sealed class NeckRequest
		{
			public Vector3 Position;

			public NeckRequest(Vector3 position)
			{
				//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)
				Position = position;
			}
		}

		private static SCP173Audio s_instance;

		private AudioClip m_neckSnap1;

		private AudioClip m_neckSnap2;

		private AudioClip m_moving;

		private AudioSource m_neckSource;

		private AudioSource m_movingSource;

		private bool m_loading;

		private bool m_loaded;

		private bool m_loggedMissing;

		private string m_neckPath1;

		private string m_neckPath2;

		private string m_movingPath;

		private Coroutine m_neckQueueRoutine;

		private readonly Queue<NeckRequest> m_neckQueue = new Queue<NeckRequest>();

		private double m_nextNeckDspTime;

		public static bool IsLoaded
		{
			get
			{
				if ((Object)(object)s_instance != (Object)null)
				{
					return s_instance.m_loaded;
				}
				return false;
			}
		}

		public static void EnsureLoaded()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			if (!((Object)(object)s_instance != (Object)null))
			{
				GameObject val = new GameObject("SCP173_Audio");
				Object.DontDestroyOnLoad((Object)val);
				s_instance = val.AddComponent<SCP173Audio>();
			}
		}

		private void Awake()
		{
			if ((Object)(object)s_instance != (Object)null && (Object)(object)s_instance != (Object)(object)this)
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
				return;
			}
			s_instance = this;
			m_neckSource = CreateSource("SCP173_NeckAudio", 0f, spatial: false);
			m_movingSource = CreateSource("SCP173_MovingAudio", 1f, spatial: true);
			StartLoading();
		}

		private AudioSource CreateSource(string name, float spatialBlend, bool spatial)
		{
			//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)
			GameObject val = new GameObject(name);
			val.transform.SetParent(((Component)this).transform, false);
			AudioSource obj = val.AddComponent<AudioSource>();
			obj.playOnAwake = false;
			obj.loop = false;
			obj.spatialBlend = spatialBlend;
			obj.volume = 1f;
			obj.ignoreListenerPause = true;
			obj.dopplerLevel = 0f;
			obj.rolloffMode = (AudioRolloffMode)1;
			obj.minDistance = (spatial ? 2f : 1f);
			obj.maxDistance = (spatial ? 80f : 500f);
			return obj;
		}

		private void StartLoading()
		{
			if (!m_loading && !m_loaded)
			{
				m_loading = true;
				((MonoBehaviour)this).StartCoroutine(LoadAllAudio());
			}
		}

		private IEnumerator LoadAllAudio()
		{
			EmbeddedAssetLoader.InitializeCache();
			EmbeddedAssetLoader.ExtractAllEmbeddedAssets();
			string cachedPath = EmbeddedAssetLoader.GetCachedPath("Assets/neck_snap_1.mp3");
			string neck2Path = EmbeddedAssetLoader.GetCachedPath("Assets/neck_snap_2.mp3");
			string movingPath = EmbeddedAssetLoader.GetCachedPath("Assets/scp-173-moving.mp3");
			m_neckPath1 = cachedPath;
			m_neckPath2 = neck2Path;
			m_movingPath = movingPath;
			yield return ((MonoBehaviour)this).StartCoroutine(LoadMp3(cachedPath, "SCP173_NeckSnap_1", delegate(AudioClip clip)
			{
				m_neckSnap1 = clip;
			}));
			yield return ((MonoBehaviour)this).StartCoroutine(LoadMp3(neck2Path, "SCP173_NeckSnap_2", delegate(AudioClip clip)
			{
				m_neckSnap2 = clip;
			}));
			yield return ((MonoBehaviour)this).StartCoroutine(LoadMp3(movingPath, "SCP173_Moving", delegate(AudioClip clip)
			{
				m_moving = clip;
			}));
			m_loading = false;
			m_loaded = (Object)(object)m_neckSnap1 != (Object)null || (Object)(object)m_neckSnap2 != (Object)null || (Object)(object)m_moving != (Object)null;
			if (!m_loaded && !m_loggedMissing)
			{
				m_loggedMissing = true;
			}
			if (m_neckQueue.Count > 0 && m_neckQueueRoutine == null)
			{
				m_neckQueueRoutine = ((MonoBehaviour)this).StartCoroutine(ProcessNeckQueue());
			}
		}

		private IEnumerator LoadMp3(string path, string clipName, Action<AudioClip> assign)
		{
			if (string.IsNullOrEmpty(path) || !File.Exists(path))
			{
				yield break;
			}
			WWW www = new WWW("file://" + path);
			yield return www;
			if (string.IsNullOrEmpty(www.error))
			{
				AudioClip audioClip = www.GetAudioClip(false, true, (AudioType)13);
				if ((Object)(object)audioClip != (Object)null)
				{
					((Object)audioClip).name = clipName;
					assign(audioClip);
				}
			}
		}

		public static void PlayNeckSnap(Vector3 worldPosition)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			EnsureLoaded();
			if (!((Object)(object)s_instance == (Object)null))
			{
				s_instance.m_neckQueue.Enqueue(new NeckRequest(worldPosition));
				if (s_instance.m_neckQueueRoutine == null)
				{
					s_instance.m_neckQueueRoutine = ((MonoBehaviour)s_instance).StartCoroutine(s_instance.ProcessNeckQueue());
				}
			}
		}

		private IEnumerator ProcessNeckQueue()
		{
			while (m_neckQueue.Count > 0)
			{
				while ((Object)(object)m_neckSnap1 == (Object)null && (Object)(object)m_neckSnap2 == (Object)null && m_loading)
				{
					yield return null;
				}
				if ((Object)(object)m_neckSnap1 == (Object)null && (Object)(object)m_neckSnap2 == (Object)null)
				{
					break;
				}
				NeckRequest neckRequest = m_neckQueue.Dequeue();
				AudioClip val = ChooseRandomNeckSnap();
				if (!((Object)(object)val == (Object)null))
				{
					double num = Math.Max(AudioSettings.dspTime + 0.01, m_nextNeckDspTime);
					((Component)m_neckSource).transform.position = neckRequest.Position;
					m_neckSource.clip = val;
					m_neckSource.PlayScheduled(num);
					double num2 = Math.Max(0.001, val.length);
					double end = (m_nextNeckDspTime = num + num2);
					while (AudioSettings.dspTime < end - 0.002)
					{
						yield return null;
					}
					m_neckSource.Stop();
					m_neckSource.clip = null;
					yield return null;
				}
			}
			m_neckQueueRoutine = null;
			if (m_neckQueue.Count > 0)
			{
				m_neckQueueRoutine = ((MonoBehaviour)this).StartCoroutine(ProcessNeckQueue());
			}
		}

		private AudioClip ChooseRandomNeckSnap()
		{
			if ((Object)(object)m_neckSnap1 != (Object)null && (Object)(object)m_neckSnap2 != (Object)null)
			{
				if (Random.Range(0, 2) != 0)
				{
					return m_neckSnap2;
				}
				return m_neckSnap1;
			}
			return m_neckSnap1 ?? m_neckSnap2;
		}

		public static void PlayMovingTeleport(Vector3 worldPosition)
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			EnsureLoaded();
			if (!((Object)(object)s_instance == (Object)null) && !((Object)(object)s_instance.m_moving == (Object)null) && !((Object)(object)s_instance.m_movingSource == (Object)null))
			{
				((Behaviour)s_instance.m_movingSource).enabled = true;
				((Component)s_instance.m_movingSource).transform.position = worldPosition;
				s_instance.m_movingSource.PlayOneShot(s_instance.m_moving, 1f);
			}
		}
	}
	public static class SCP173Config
	{
		public const string PluginGuid = "belpinex.tabs.scp173";

		public const string PluginName = "SCP-173 (Faccion Custom)";

		public const string PluginVersion = "1.1.4";

		public const string ObjResource = "Assets/SCP173.obj";

		public const string DiffuseResource = "Assets/SCP173_Diffuse.jpg";

		public const string NormalResource = "Assets/SCP173_Normal.jpg";

		public const string SpecResource = "Assets/SCP173_Spec.jpg";

		public const string NeckSnapResource = "Assets/neck_snap_2.mp3";

		public const string NeckSnapResource1 = "Assets/neck_snap_1.mp3";

		public const string NeckSnapResource2 = "Assets/neck_snap_2.mp3";

		public const string MovingResource = "Assets/scp-173-moving.mp3";

		public const float TeleportRange = 6f;

		public const float BlindTeleportSpeed = 400f;

		public const float KillDistance = 1.6f;

		public const float AttackCooldown = 1.25f;

		public const float EnemyVisionConeAngle = 140f;

		public const float EnemyVisionRange = 60f;

		public const string OcclusionLayerMaskName = "Default";

		public const float NeckSnapDuration = 0.35f;

		public const float NeckSnapAngle = 110f;

		public const float OutOfMapY = -250f;

		public const float GroundProbeHeight = 8f;

		public const float GroundProbeDistance = 2000f;

		public const float GroundEpsilon = 0.015f;

		public static string PluginFolder => Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);

		public static string AssetsFolder => Path.Combine(PluginFolder, "Assets");

		public static string ObjPath => Path.Combine(AssetsFolder, "SCP173.obj");

		public static string DiffusePath => Path.Combine(AssetsFolder, "SCP173_Diffuse.jpg");

		public static string NormalPath => Path.Combine(AssetsFolder, "SCP173_Normal.jpg");

		public static string SpecPath => Path.Combine(AssetsFolder, "SCP173_Spec.jpg");

		public static string NeckSnapAudioPath => Path.Combine(AssetsFolder, "neck_snap_2.mp3");
	}
	public static class SCP173CorpseFactory
	{
		public static GameObject Create(Unit victim, float neckAngle)
		{
			//IL_001e: 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)
			if ((Object)(object)victim == (Object)null)
			{
				return null;
			}
			GameObject val = null;
			SCP173Runtime.BeginInternalMutation();
			try
			{
				val = Object.Instantiate<GameObject>(((Component)victim).gameObject, ((Component)victim).transform.position, ((Component)victim).transform.rotation);
				if ((Object)(object)val == (Object)null)
				{
					return null;
				}
				((Object)val).name = ((Object)((Component)victim).gameObject).name + " [SCP-173 Ragdoll]";
				val.tag = "Untagged";
				DisableBehaviourComponents(val);
				MakeRagdollOnly(val);
				TwistAndBreakNeck(val.transform, neckAngle);
				val.SetActive(true);
			}
			catch (Exception)
			{
				if ((Object)(object)val != (Object)null)
				{
					Object.DestroyImmediate((Object)(object)val);
				}
				val = null;
			}
			finally
			{
				SCP173Runtime.EndInternalMutation();
			}
			return val;
		}

		private static void DisableBehaviourComponents(GameObject corpse)
		{
			MonoBehaviour[] componentsInChildren = corpse.GetComponentsInChildren<MonoBehaviour>(true);
			foreach (MonoBehaviour val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null))
				{
					Object.DestroyImmediate((Object)(object)val);
				}
			}
		}

		private static void MakeRagdollOnly(GameObject corpse)
		{
			//IL_004b: 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)
			Component[] componentsInChildren = corpse.GetComponentsInChildren<Component>(true);
			foreach (Component val in componentsInChildren)
			{
				if ((Object)(object)val == (Object)null || val is Transform)
				{
					continue;
				}
				Rigidbody val2 = (Rigidbody)(object)((val is Rigidbody) ? val : null);
				if (val2 != null)
				{
					val2.isKinematic = false;
					val2.detectCollisions = true;
					val2.useGravity = true;
					val2.constraints = (RigidbodyConstraints)0;
					val2.velocity = Vector3.zero;
					val2.angularVelocity = Vector3.zero;
				}
				else
				{
					Collider val3 = (Collider)(object)((val is Collider) ? val : null);
					if (val3 != null)
					{
						val3.enabled = true;
					}
					else if (!(val is Joint) && !(val is Renderer) && !(val is MeshFilter))
					{
						Object.DestroyImmediate((Object)(object)val);
					}
				}
			}
		}

		private static void TwistAndBreakNeck(Transform root, float angleDegrees)
		{
			//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_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_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_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: 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_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)
			//IL_00b9: 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_00d5: Unknown result type (might be due to invalid IL or missing references)
			Rigidbody val = FindBody(root, "Head", "head");
			Rigidbody val2 = FindBody(root, "Torso", "torso", "Chest", "chest");
			if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
			{
				return;
			}
			Vector3 right = ((Component)val2).transform.right;
			((Component)val).transform.rotation = Quaternion.AngleAxis(angleDegrees, right) * ((Component)val).transform.rotation;
			val.angularVelocity = right * (angleDegrees * ((float)Math.PI / 180f)) * 5f;
			Vector3 val3 = val.worldCenterOfMass - val2.worldCenterOfMass;
			if (((Vector3)(ref val3)).sqrMagnitude > 0.0001f)
			{
				val.AddForce(((Vector3)(ref val3)).normalized * 1.5f, (ForceMode)2);
			}
			Joint[] componentsInChildren = ((Component)root).GetComponentsInChildren<Joint>(true);
			foreach (Joint val4 in componentsInChildren)
			{
				if (!((Object)(object)val4 == (Object)null))
				{
					Rigidbody connectedBody = val4.connectedBody;
					Rigidbody component = ((Component)val4).GetComponent<Rigidbody>();
					if ((Object)(object)((Component)val4).transform == (Object)(object)((Component)val).transform || ((Component)val4).transform.IsChildOf(((Component)val).transform) || (Object)(object)component == (Object)(object)val || (Object)(object)connectedBody == (Object)(object)val || ((Object)(object)component == (Object)(object)val2 && (Object)(object)connectedBody == (Object)(object)val) || ((Object)(object)connectedBody == (Object)(object)val2 && (Object)(object)component == (Object)(object)val))
					{
						Object.DestroyImmediate((Object)(object)val4);
					}
				}
			}
		}

		private static Rigidbody FindBody(Transform root, params string[] names)
		{
			Transform[] componentsInChildren = ((Component)root).GetComponentsInChildren<Transform>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				string name = ((Object)componentsInChildren[i]).name;
				for (int j = 0; j < names.Length; j++)
				{
					if (string.Equals(name, names[j], StringComparison.OrdinalIgnoreCase))
					{
						return ((Component)componentsInChildren[i]).GetComponent<Rigidbody>();
					}
				}
			}
			return null;
		}
	}
	public class SCP173HazardController : MonoBehaviour
	{
		private struct VisionCandidate
		{
			internal Unit unit;

			internal Transform eye;

			internal Vector3 direction;

			internal float distance;

			internal float score;

			internal VisionCandidate(Unit u, Transform e, Vector3 d, float dist, float s)
			{
				//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)
				unit = u;
				eye = e;
				direction = d;
				distance = dist;
				score = s;
			}

			internal static int Compare(VisionCandidate a, VisionCandidate b)
			{
				return b.score.CompareTo(a.score);
			}
		}

		private Transform m_currentTarget;

		private Unit m_currentTargetUnit;

		private bool m_isBeingSeen;

		private readonly List<Unit> m_allEnemyUnitsBuffer = new List<Unit>();

		private float m_targetRescanTimer;

		private float m_nextAttackTime;

		private Vector3 m_lastSafePosition;

		private const float TargetRescanInterval = 0.25f;

		private LayerMask m_occlusionMask;

		private const int MaxVisionRaycastsPerFrame = 24;

		private const float VisionCacheDuration = 0.035f;

		private float m_nextVisionCheckTime;

		private bool m_cachedBeingSeen;

		private static readonly List<VisionCandidate> s_visionCandidates = new List<VisionCandidate>(64);

		private void Awake()
		{
			//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)
			m_occlusionMask = LayerMask.op_Implicit(LayerMask.GetMask(new string[1] { "Default" }));
		}

		private void Start()
		{
			//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)
			if (SCP173Runtime.TryRegisterInstance(this))
			{
				m_lastSafePosition = ((Component)this).transform.position;
				SCP173Audio.EnsureLoaded();
				RescanTarget();
			}
		}

		private void OnDestroy()
		{
			SCP173Runtime.NotifyInstanceDestroyed(this);
		}

		private void Update()
		{
			MaintainGroundedAndRecover();
			m_isBeingSeen = IsBeingSeenByAnyEnemy();
			if (!m_isBeingSeen)
			{
				m_targetRescanTimer -= Time.unscaledDeltaTime;
				if ((Object)(object)m_currentTargetUnit == (Object)null || m_currentTargetUnit.dead || m_targetRescanTimer <= 0f)
				{
					RescanTarget();
					m_targetRescanTimer = 0.25f;
				}
				if (!((Object)(object)m_currentTarget == (Object)null))
				{
					StepTeleportTowardsTarget();
				}
			}
		}

		private void MaintainGroundedAndRecover()
		{
			//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_0014: 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_0028: 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_008b: 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_00c4: 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_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_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_00b3: 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_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = ((Component)this).transform.position;
			if (!IsFinite(val) || val.y < -250f)
			{
				if (TryGetGroundedPosition(m_lastSafePosition, out var grounded))
				{
					SCP173Runtime.BeginInternalMutation();
					try
					{
						((Component)this).transform.position = grounded;
					}
					finally
					{
						SCP173Runtime.EndInternalMutation();
					}
					val = grounded;
				}
				else
				{
					if (!TryGetGroundedPosition(val, out grounded))
					{
						return;
					}
					SCP173Runtime.BeginInternalMutation();
					try
					{
						((Component)this).transform.position = grounded;
					}
					finally
					{
						SCP173Runtime.EndInternalMutation();
					}
					val = grounded;
				}
			}
			if (!TryGetGroundedPosition(val, out var grounded2))
			{
				return;
			}
			float num = Mathf.Abs(grounded2.y - val.y);
			if (num > 0.01f && num < 12f)
			{
				SCP173Runtime.BeginInternalMutation();
				try
				{
					((Component)this).transform.position = grounded2;
				}
				finally
				{
					SCP173Runtime.EndInternalMutation();
				}
				val = grounded2;
			}
			m_lastSafePosition = grounded2;
			SCP173Runtime.RememberTransform(((Component)this).transform);
		}

		private bool TryGetGroundedPosition(Vector3 candidate, out Vector3 grounded)
		{
			//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_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_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_00da: 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_00fb: 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_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_00cc: 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)
			grounded = candidate;
			if (!IsFinite(candidate))
			{
				return false;
			}
			RaycastHit[] array = Physics.RaycastAll(candidate + Vector3.up * 60f, Vector3.down, 4060f, -1, (QueryTriggerInteraction)1);
			float num = float.NegativeInfinity;
			bool flag = false;
			for (int i = 0; i < array.Length; i++)
			{
				RaycastHit val = array[i];
				Transform transform = ((RaycastHit)(ref val)).transform;
				if (!((Object)(object)transform == (Object)null) && !IsPartOfSCP173(transform) && !((Object)(object)((Component)transform).GetComponentInParent<Unit>() != (Object)null))
				{
					float y = ((RaycastHit)(ref val)).point.y;
					if (y > num)
					{
						num = y;
						flag = true;
					}
				}
			}
			if (!flag)
			{
				return false;
			}
			Renderer componentInChildren = ((Component)this).GetComponentInChildren<Renderer>();
			float num2 = 0f;
			if ((Object)(object)componentInChildren != (Object)null)
			{
				float y2 = candidate.y;
				Bounds bounds = componentInChildren.bounds;
				num2 = y2 - ((Bounds)(ref bounds)).min.y;
			}
			grounded = new Vector3(candidate.x, num + num2 + 0.015f, candidate.z);
			if (IsFinite(grounded))
			{
				return grounded.y > -250f;
			}
			return false;
		}

		private bool IsBeingSeenByAnyEnemy()
		{
			//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_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: 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_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			float unscaledTime = Time.unscaledTime;
			if (unscaledTime < m_nextVisionCheckTime)
			{
				return m_cachedBeingSeen;
			}
			m_nextVisionCheckTime = unscaledTime + 0.035f;
			m_allEnemyUnitsBuffer.Clear();
			UnitRegistry.GetAllLivingUnits(m_allEnemyUnitsBuffer);
			Vector3 position = ((Component)this).transform.position;
			float num = 3600f;
			List<VisionCandidate> list = s_visionCandidates;
			list.Clear();
			for (int i = 0; i < m_allEnemyUnitsBuffer.Count; i++)
			{
				Unit val = m_allEnemyUnitsBuffer[i];
				if ((Object)(object)val == (Object)null || SCP173Runtime.HasNeckBeenBroken(val) || val.dead || (Object)(object)val.data == (Object)null || (Object)(object)val.Head == (Object)null)
				{
					continue;
				}
				Transform head = val.Head;
				Vector3 val2 = position - head.position;
				float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude;
				if (!(sqrMagnitude <= 0.0001f) && !(sqrMagnitude > num))
				{
					float num2 = 1f / Mathf.Sqrt(sqrMagnitude);
					Vector3 val3 = val2 * num2;
					float num3 = Vector3.Dot(head.forward, val3);
					float num4 = Mathf.Cos(1.2217305f);
					if (!(num3 < num4))
					{
						float s = num3 * 2f - sqrMagnitude / num;
						list.Add(new VisionCandidate(val, head, val3, Mathf.Sqrt(sqrMagnitude), s));
					}
				}
			}
			list.Sort(VisionCandidate.Compare);
			int num5 = Mathf.Min(24, list.Count);
			RaycastHit val4 = default(RaycastHit);
			for (int j = 0; j < num5; j++)
			{
				VisionCandidate visionCandidate = list[j];
				if (!Physics.Raycast(visionCandidate.eye.position, visionCandidate.direction, ref val4, visionCandidate.distance + 0.5f, LayerMask.op_Implicit(m_occlusionMask), (QueryTriggerInteraction)1) || IsPartOfSCP173(((RaycastHit)(ref val4)).transform))
				{
					m_cachedBeingSeen = true;
					return true;
				}
			}
			m_cachedBeingSeen = false;
			return false;
		}

		private bool IsPartOfSCP173(Transform t)
		{
			if (!((Object)(object)t == (Object)(object)((Component)this).transform))
			{
				return t.IsChildOf(((Component)this).transform);
			}
			return true;
		}

		private static bool IsFinite(Vector3 p)
		{
			//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)
			//IL_001a: 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_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			if (!float.IsNaN(p.x) && !float.IsNaN(p.y) && !float.IsNaN(p.z) && !float.IsInfinity(p.x) && !float.IsInfinity(p.y))
			{
				return !float.IsInfinity(p.z);
			}
			return false;
		}

		private void RescanTarget()
		{
			//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_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			m_allEnemyUnitsBuffer.Clear();
			UnitRegistry.GetAllLivingUnits(m_allEnemyUnitsBuffer);
			float num = float.MaxValue;
			Unit val = null;
			Vector3 position = ((Component)this).transform.position;
			for (int i = 0; i < m_allEnemyUnitsBuffer.Count; i++)
			{
				Unit val2 = m_allEnemyUnitsBuffer[i];
				if (!((Object)(object)val2 == (Object)null) && !SCP173Runtime.HasNeckBeenBroken(val2) && !val2.dead && !((Object)(object)val2.data == (Object)null) && !((Object)(object)val2.data.mainRig == (Object)null))
				{
					Vector3 val3 = val2.data.mainRig.position - position;
					float sqrMagnitude = ((Vector3)(ref val3)).sqrMagnitude;
					if (sqrMagnitude < num)
					{
						num = sqrMagnitude;
						val = val2;
					}
				}
			}
			m_currentTargetUnit = val;
			m_currentTarget = (((Object)(object)val != (Object)null) ? ((Component)val.data.mainRig).transform : null);
		}

		private void StepTeleportTowardsTarget()
		{
			//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_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_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_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_00af: 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_00b6: 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_00b9: 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_00c7: 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_00e1: 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_00f8: 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_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			Vector3 position = ((Component)this).transform.position;
			Vector3 position2 = m_currentTarget.position;
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor(position2.x - position.x, 0f, position2.z - position.z);
			float magnitude = ((Vector3)(ref val)).magnitude;
			if (magnitude <= 1.6f)
			{
				float unscaledTime = Time.unscaledTime;
				if (unscaledTime >= m_nextAttackTime)
				{
					ExecuteInstantKill(m_currentTargetUnit);
					m_nextAttackTime = unscaledTime + 1.25f;
				}
				return;
			}
			float num = 400f * Time.unscaledDeltaTime;
			num = Mathf.Min(new float[3] { num, 6f, magnitude });
			if (num <= 0f)
			{
				return;
			}
			Vector3 val2 = val / magnitude;
			Vector3 candidate = position + val2 * num;
			if (!TryGetGroundedPosition(candidate, out var grounded))
			{
				return;
			}
			SCP173Runtime.BeginInternalMutation();
			try
			{
				((Component)this).transform.position = grounded;
			}
			finally
			{
				SCP173Runtime.EndInternalMutation();
			}
			SCP173Audio.PlayMovingTeleport(grounded);
			m_lastSafePosition = grounded;
			SCP173Runtime.RememberTransform(((Component)this).transform);
			if (!(((Vector3)(ref val2)).sqrMagnitude > 0.0001f))
			{
				return;
			}
			SCP173Runtime.BeginInternalMutation();
			try
			{
				((Component)this).transform.rotation = Quaternion.LookRotation(val2, Vector3.up);
			}
			finally
			{
				SCP173Runtime.EndInternalMutation();
			}
		}

		private void ExecuteInstantKill(Unit victim)
		{
			//IL_004b: 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)
			if ((Object)(object)victim == (Object)null || victim.dead || (Object)(object)victim.data == (Object)null)
			{
				return;
			}
			SCP173Audio.PlayNeckSnap(((Object)(object)victim.data.mainRig != (Object)null) ? victim.data.mainRig.position : ((Component)victim).transform.position);
			NeckSnapDeformer.SnapNeck(victim, 110f);
			GameObject val = SCP173CorpseFactory.Create(victim, 110f);
			UnitRegistry.Unregister(victim);
			SCP173ReferencePurger.Purge(victim);
			SCP173Runtime.BeginInternalMutation();
			try
			{
				if ((Object)(object)victim != (Object)null)
				{
					Object.DestroyImmediate((Object)(object)((Component)victim).gameObject);
				}
			}
			finally
			{
				SCP173Runtime.EndInternalMutation();
			}
			if ((Object)(object)val != (Object)null)
			{
				Rigidbody[] componentsInChildren = val.GetComponentsInChildren<Rigidbody>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					if ((Object)(object)componentsInChildren[i] != (Object)null)
					{
						componentsInChildren[i].WakeUp();
					}
				}
			}
			m_currentTarget = null;
			m_currentTargetUnit = null;
		}
	}
	public static class SCP173ReferencePurger
	{
		public static void Purge(Unit victim)
		{
			if ((Object)(object)victim == (Object)null)
			{
				return;
			}
			Guid guid = ((victim.RuntimeReference != null) ? ((RuntimeReference)victim.RuntimeReference).Guid : Guid.Empty);
			UnitBlueprint unitBlueprint = victim.unitBlueprint;
			victim.RuntimeReference = null;
			RemoveRuntimeReference(guid);
			RemoveFromTeamSystem(victim);
			ClearRuntimeReferenceFields(((Component)victim).gameObject);
			try
			{
				if ((Object)(object)unitBlueprint != (Object)null)
				{
					UnitBlueprint val = Object.Instantiate<UnitBlueprint>(unitBlueprint);
					((Object)val).name = ((Object)unitBlueprint).name + " [SCP173_CORRUPTED_RUNTIME]";
					val.UnitBase = null;
					val.RightWeapon = null;
					val.LeftWeapon = null;
					val.fistRef = null;
					victim.unitBlueprint = val;
				}
			}
			catch (Exception)
			{
				victim.unitBlueprint = null;
			}
		}

		private static void RemoveRuntimeReference(Guid guid)
		{
			if (guid == Guid.Empty)
			{
				return;
			}
			try
			{
				RuntimeReferenceService val = Object.FindObjectOfType<RuntimeReferenceService>();
				if ((Object)(object)val == (Object)null)
				{
					return;
				}
				FieldInfo field = typeof(RuntimeReferenceService).GetField("m_references", BindingFlags.Instance | BindingFlags.NonPublic);
				((field != null) ? (field.GetValue(val) as IDictionary) : null)?.Remove(guid);
				List<RuntimeReference> allReferencesRequests = val.GetAllReferencesRequests();
				if (allReferencesRequests == null)
				{
					return;
				}
				for (int num = allReferencesRequests.Count - 1; num >= 0; num--)
				{
					RuntimeReference val2 = allReferencesRequests[num];
					if (val2 != null && val2.Guid == guid)
					{
						allReferencesRequests.RemoveAt(num);
					}
				}
			}
			catch (Exception)
			{
			}
		}

		private static void RemoveFromTeamSystem(Unit victim)
		{
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				World active = World.Active;
				if (active == null)
				{
					return;
				}
				TeamSystem existingManager = active.GetExistingManager<TeamSystem>();
				if (existingManager == null)
				{
					return;
				}
				Component val = FindComponentByName(((Component)victim).gameObject, "GameObjectEntity");
				if ((Object)(object)val != (Object)null)
				{
					object obj = ((object)val).GetType().GetProperty("Entity", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(val, null);
					MethodInfo method = typeof(TeamSystem).GetMethod("RemoveEntity", BindingFlags.Instance | BindingFlags.Public);
					if (method != null && obj != null)
					{
						method.Invoke(existingManager, new object[3] { obj, victim.Team, victim });
						return;
					}
				}
				RemoveUnitFromPrivateList(existingManager, "m_allUnits", victim);
				RemoveUnitFromPrivateList(existingManager, "m_teamUnits", victim);
				RemoveUnitFromPrivateList(existingManager, "m_winConditionUnits", victim);
			}
			catch (Exception)
			{
			}
		}

		private static Component FindComponentByName(GameObject go, string typeName)
		{
			Component[] components = go.GetComponents<Component>();
			for (int i = 0; i < components.Length; i++)
			{
				if ((Object)(object)components[i] != (Object)null && ((object)components[i]).GetType().Name == typeName)
				{
					return components[i];
				}
			}
			return null;
		}

		private static void RemoveUnitFromPrivateList(TeamSystem teams, string fieldName, Unit victim)
		{
			object obj = typeof(TeamSystem).GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(teams);
			if (obj is IDictionary dictionary)
			{
				{
					foreach (object item in new ArrayList(dictionary.Keys))
					{
						(dictionary[item] as IList)?.Remove(victim);
					}
					return;
				}
			}
			(obj as IList)?.Remove(victim);
		}

		private static void ClearRuntimeReferenceFields(GameObject root)
		{
			MonoBehaviour[] componentsInChildren = root.GetComponentsInChildren<MonoBehaviour>(true);
			foreach (MonoBehaviour val in componentsInChildren)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				FieldInfo[] fields = ((object)val).GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (FieldInfo fieldInfo in fields)
				{
					if (typeof(RuntimeReference).IsAssignableFrom(fieldInfo.FieldType))
					{
						try
						{
							fieldInfo.SetValue(val, null);
						}
						catch
						{
						}
					}
				}
			}
		}
	}
	public static class SCP173Runtime
	{
		private static Unit s_referenceProxy;

		private static SCP173HazardController s_instance;

		private static GameObject s_instanceObject;

		private static Vector3 s_lastPosition;

		private static Quaternion s_lastRotation = Quaternion.identity;

		private static string s_sceneName;

		private static Guid s_referenceGuid = Guid.Empty;

		private static bool s_referenceBound;

		private static bool s_spawnInProgress;

		private static int s_timeServiceTouchCount;

		private static bool s_internalMutation;

		private static readonly HashSet<Guid> s_neckBrokenRuntimeGuids = new HashSet<Guid>();

		private static Vector3 s_expectedScale = Vector3.one;

		private static Mesh s_expectedMesh;

		private static Material s_expectedMaterial;

		public static SCP173HazardController Instance => s_instance;

		public static GameObject InstanceObject => s_instanceObject;

		public static Unit ReferenceProxy => s_referenceProxy;

		public static Guid ReferenceGuid => s_referenceGuid;

		public static bool HasReference
		{
			get
			{
				if (s_referenceBound)
				{
					return s_referenceGuid != Guid.Empty;
				}
				return false;
			}
		}

		public static bool HasSpawned => IsValid((Object)(object)s_instance);

		public static bool SpawnInProgress => s_spawnInProgress;

		public static string SceneName => s_sceneName;

		public static int TimeServiceTouchCount => s_timeServiceTouchCount;

		public static bool InternalMutation => s_internalMutation;

		public static Vector3 ExpectedScale => s_expectedScale;

		public static Mesh ExpectedMesh => s_expectedMesh;

		public static Material ExpectedMaterial => s_expectedMaterial;

		public static Vector3 LastPosition => s_lastPosition;

		public static Quaternion LastRotation => s_lastRotation;

		public static void MarkTimeServiceTouched()
		{
			s_timeServiceTouchCount++;
		}

		public static void BeginInternalMutation()
		{
			s_internalMutation = true;
		}

		public static void EndInternalMutation()
		{
			s_internalMutation = false;
		}

		public static bool IsReferenceProxy(Unit unit)
		{
			if ((Object)(object)unit != (Object)null)
			{
				return (Object)(object)s_referenceProxy == (Object)(object)unit;
			}
			return false;
		}

		public static bool IsProtectedReference(RuntimeReference reference)
		{
			if (reference != null && HasReference)
			{
				return reference.Guid == s_referenceGuid;
			}
			return false;
		}

		public static bool IsProtectedUnit(Unit unit)
		{
			if (!IsReferenceProxy(unit))
			{
				if ((Object)(object)unit != (Object)null && unit.RuntimeReference != null)
				{
					return IsProtectedReference((RuntimeReference)(object)unit.RuntimeReference);
				}
				return false;
			}
			return true;
		}

		public static bool HasNeckBeenBroken(Unit unit)
		{
			if ((Object)(object)unit == (Object)null)
			{
				return true;
			}
			if (unit.RuntimeReference != null && ((RuntimeReference)unit.RuntimeReference).Guid != Guid.Empty && s_neckBrokenRuntimeGuids.Contains(((RuntimeReference)unit.RuntimeReference).Guid))
			{
				return true;
			}
			return false;
		}

		public static void MarkNeckBroken(Unit unit)
		{
			if (!((Object)(object)unit == (Object)null) && unit.RuntimeReference != null && ((RuntimeReference)unit.RuntimeReference).Guid != Guid.Empty)
			{
				s_neckBrokenRuntimeGuids.Add(((RuntimeReference)unit.RuntimeReference).Guid);
			}
		}

		public static void BindReference(Unit proxy)
		{
			if (!((Object)(object)proxy == (Object)null) && DummyUnitFactory.IsDummy(proxy))
			{
				s_referenceProxy = proxy;
				if (proxy.RuntimeReference != null)
				{
					s_referenceGuid = ((RuntimeReference)proxy.RuntimeReference).Guid;
					s_referenceBound = s_referenceGuid != Guid.Empty;
				}
			}
		}

		public static bool TryRegisterInstance(SCP173HazardController controller)
		{
			//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_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_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_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)controller == (Object)null)
			{
				return false;
			}
			if (IsValid((Object)(object)s_instance) && (Object)(object)s_instance != (Object)(object)controller)
			{
				BeginInternalMutation();
				try
				{
					Object.DestroyImmediate((Object)(object)((Component)controller).gameObject);
				}
				finally
				{
					EndInternalMutation();
				}
				return false;
			}
			s_instance = controller;
			s_instanceObject = ((Component)controller).gameObject;
			s_lastPosition = ((Component)controller).transform.position;
			s_lastRotation = ((Component)controller).transform.rotation;
			Scene activeScene = SceneManager.GetActiveScene();
			s_sceneName = ((Scene)(ref activeScene)).name;
			MeshFilter component = ((Component)controller).GetComponent<MeshFilter>();
			MeshRenderer component2 = ((Component)controller).GetComponent<MeshRenderer>();
			s_expectedScale = ((Component)controller).transform.localScale;
			s_expectedMesh = (((Object)(object)component != (Object)null) ? component.sharedMesh : null);
			s_expectedMaterial = (((Object)(object)component2 != (Object)null) ? ((Renderer)component2).sharedMaterial : null);
			return true;
		}

		public static void RememberTransform(Transform transform)
		{
			//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_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)
			if (!((Object)(object)transform == (Object)null) && !InternalMutation)
			{
				s_lastPosition = transform.position;
				s_lastRotation = transform.rotation;
			}
		}

		public static bool IsSameScene()
		{
			//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)
			if (!string.IsNullOrEmpty(s_sceneName))
			{
				Scene activeScene = SceneManager.GetActiveScene();
				return ((Scene)(ref activeScene)).name == s_sceneName;
			}
			return false;
		}

		public static void SetSpawnInProgress(bool value)
		{
			s_spawnInProgress = value;
		}

		public static void NotifyInstanceDestroyed(SCP173HazardController controller)
		{
			if (!((Object)(object)s_instance != (Object)(object)controller))
			{
				if (!InternalMutation)
				{
					RememberTransform(((Component)controller).transform);
				}
				s_instance = null;
				s_instanceObject = null;
			}
		}

		public static bool TryGetLiveInstance(out SCP173HazardController controller)
		{
			controller = s_instance;
			return IsValid((Object)(object)controller);
		}

		public static void ResetSceneState()
		{
			//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_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)
			s_referenceProxy = null;
			s_instance = null;
			s_instanceObject = null;
			s_lastPosition = Vector3.zero;
			s_referenceGuid = Guid.Empty;
			s_referenceBound = false;
			s_sceneName = null;
			s_spawnInProgress = false;
			s_timeServiceTouchCount = 0;
			s_internalMutation = false;
			s_neckBrokenRuntimeGuids.Clear();
			s_expectedScale = Vector3.one;
			s_expectedMesh = null;
			s_expectedMaterial = null;
		}

		private static bool IsValid(Object obj)
		{
			return obj != (Object)null;
		}
	}
	public static class SCP173SpawnReplacer
	{
		private static Mesh s_cachedMesh;

		private static Material s_cachedMaterial;

		private static Texture2D s_cachedDiffuse;

		private static Texture2D s_cachedNormal;

		private static Texture2D s_cachedSpec;

		public static void ReplaceIfDummy(Unit unit)
		{
			//IL_002f: 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)
			if (!DummyUnitFactory.IsDummy(unit))
			{
				return;
			}
			if (SCP173Runtime.HasSpawned || SCP173Runtime.SpawnInProgress)
			{
				Object.Destroy((Object)(object)((Component)unit).gameObject);
				return;
			}
			SCP173Runtime.SetSpawnInProgress(value: true);
			try
			{
				SpawnRealSCP173(((Component)unit).transform.position, ((Component)unit).transform.rotation);
				NeutralizeReferenceProxy(unit);
			}
			finally
			{
				SCP173Runtime.SetSpawnInProgress(value: false);
			}
		}

		private static void NeutralizeReferenceProxy(Unit unit)
		{
			if ((Object)(object)unit == (Object)null)
			{
				return;
			}
			unit.ShowRenderers(false);
			Collider[] componentsInChildren = ((Component)unit).GetComponentsInChildren<Collider>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if ((Object)(object)componentsInChildren[i] != (Object)null)
				{
					componentsInChildren[i].enabled = false;
				}
			}
			MonoBehaviour[] componentsInChildren2 = ((Component)unit).GetComponentsInChildren<MonoBehaviour>(true);
			foreach (MonoBehaviour val in componentsInChildren2)
			{
				if (!((Object)(object)val == (Object)null) && !(val is Unit))
				{
					((Behaviour)val).enabled = false;
				}
			}
			try
			{
				UnitAPI component = ((Component)unit).GetComponent<UnitAPI>();
				if ((Object)(object)component != (Object)null)
				{
					component.SetIsDead();
					((Behaviour)component).enabled = false;
				}
			}
			catch
			{
			}
			((Behaviour)unit).enabled = false;
		}

		private static GameObject SpawnRealSCP173(Vector3 position, Quaternion rotation)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			//IL_0027: 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_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_0050: 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_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: 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_00bd: 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_00ca: Unknown result type (might be due to invalid IL or missing references)
			EnsureAssetsLoaded();
			GameObject instanceObject = SCP173Runtime.InstanceObject;
			if ((Object)(object)instanceObject != (Object)null)
			{
				return instanceObject;
			}
			GameObject val = new GameObject("SCP-173");
			val.transform.SetPositionAndRotation(position, rotation);
			float num;
			Bounds bounds;
			if (!((Object)(object)s_cachedMesh != (Object)null))
			{
				num = 0f;
			}
			else
			{
				bounds = s_cachedMesh.bounds;
				num = ((Bounds)(ref bounds)).size.y;
			}
			float num2 = num;
			float num3 = ((num2 > 0.001f) ? (2.7f / num2) : 1f);
			val.transform.localScale = Vector3.one * num3;
			if ((Object)(object)s_cachedMesh != (Object)null)
			{
				bounds = s_cachedMesh.bounds;
				float num4 = ((Bounds)(ref bounds)).min.y * num3;
				Transform transform = val.transform;
				transform.position += Vector3.up * (0f - num4);
			}
			val.AddComponent<MeshFilter>().sharedMesh = s_cachedMesh;
			MeshRenderer obj = val.AddComponent<MeshRenderer>();
			((Renderer)obj).sharedMaterial = s_cachedMaterial;
			((Renderer)obj).shadowCastingMode = (ShadowCastingMode)1;
			MeshCollider obj2 = val.AddComponent<MeshCollider>();
			obj2.sharedMesh = s_cachedMesh;
			obj2.convex = true;
			if (!SCP173Runtime.TryRegisterInstance(val.AddComponent<SCP173HazardController>()))
			{
				Object.Destroy((Object)(object)val);
				return null;
			}
			return val;
		}

		internal static Material CreateProtectedMaterial()
		{
			EnsureAssetsLoaded();
			return s_cachedMaterial;
		}

		public static void PreloadAssets()
		{
			EnsureAssetsLoaded();
		}

		private static void EnsureAssetsLoaded()
		{
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Expected O, but got Unknown
			if ((Object)(object)s_cachedMesh == (Object)null)
			{
				string cachedPath = EmbeddedAssetLoader.GetCachedPath("Assets/SCP173.obj");
				if (!string.IsNullOrEmpty(cachedPath))
				{
					s_cachedMesh = ObjRuntimeLoader.LoadMesh(cachedPath);
				}
				if ((Object)(object)s_cachedMesh == (Object)null)
				{
					s_cachedMesh = ObjRuntimeLoader.LoadMeshFromText(EmbeddedAssetLoader.LoadText("Assets/SCP173.obj"));
				}
			}
			if ((Object)(object)s_cachedDiffuse == (Object)null)
			{
				string cachedPath2 = EmbeddedAssetLoader.GetCachedPath("Assets/SCP173_Diffuse.jpg");
				if (!string.IsNullOrEmpty(cachedPath2))
				{
					s_cachedDiffuse = ObjRuntimeLoader.LoadTexture(cachedPath2);
				}
				if ((Object)(object)s_cachedDiffuse == (Object)null)
				{
					s_cachedDiffuse = ObjRuntimeLoader.LoadTextureBytes(EmbeddedAssetLoader.LoadBytes("Assets/SCP173_Diffuse.jpg"), "SCP173_Diffuse");
				}
			}
			if ((Object)(object)s_cachedNormal == (Object)null)
			{
				string cachedPath3 = EmbeddedAssetLoader.GetCachedPath("Assets/SCP173_Normal.jpg");
				if (!string.IsNullOrEmpty(cachedPath3))
				{
					s_cachedNormal = ObjRuntimeLoader.LoadTexture(cachedPath3);
				}
				if ((Object)(object)s_cachedNormal == (Object)null)
				{
					s_cachedNormal = ObjRuntimeLoader.LoadTextureBytes(EmbeddedAssetLoader.LoadBytes("Assets/SCP173_Normal.jpg"), "SCP173_Normal");
				}
			}
			if ((Object)(object)s_cachedSpec == (Object)null)
			{
				string cachedPath4 = EmbeddedAssetLoader.GetCachedPath("Assets/SCP173_Spec.jpg");
				if (!string.IsNullOrEmpty(cachedPath4))
				{
					s_cachedSpec = ObjRuntimeLoader.LoadTexture(cachedPath4);
				}
				if ((Object)(object)s_cachedSpec == (Object)null)
				{
					s_cachedSpec = ObjRuntimeLoader.LoadTextureBytes(EmbeddedAssetLoader.LoadBytes("Assets/SCP173_Spec.jpg"), "SCP173_Spec");
				}
			}
			if ((Object)(object)s_cachedMaterial != (Object)null)
			{
				return;
			}
			Shader val = Shader.Find("Standard") ?? Shader.Find("Legacy Shaders/Bumped Specular") ?? Shader.Find("Legacy Shaders/Diffuse") ?? Shader.Find("Diffuse") ?? Shader.Find("Unlit/Texture");
			if (!((Object)(object)val == (Object)null))
			{
				Material val2 = new Material(val)
				{
					name = "SCP173_Material"
				};
				if ((Object)(object)s_cachedDiffuse != (Object)null)
				{
					val2.SetTexture("_MainTex", (Texture)(object)s_cachedDiffuse);
				}
				if ((Object)(object)s_cachedNormal != (Object)null)
				{
					val2.SetTexture("_BumpMap", (Texture)(object)s_cachedNormal);
					val2.EnableKeyword("_NORMALMAP");
				}
				if ((Object)(object)s_cachedSpec != (Object)null)
				{
					val2.SetTexture("_SpecGlossMap", (Texture)(object)s_cachedSpec);
					val2.EnableKeyword("_SPECGLOSSMAP");
				}
				s_cachedMaterial = val2;
			}
		}
	}
	public static class SCP173UnityProtectionPatches
	{
		internal static bool Is173(GameObject go)
		{
			if ((Object)(object)go == (Object)null || SCP173Runtime.InternalMutation)
			{
				return false;
			}
			GameObject instanceObject = SCP173Runtime.InstanceObject;
			if ((Object)(object)instanceObject == (Object)null)
			{
				return false;
			}
			if (!((Object)(object)go == (Object)(object)instanceObject))
			{
				return go.transform.IsChildOf(instanceObject.transform);
			}
			return true;
		}

		internal static bool Is173(Component component)
		{
			if ((Object)(object)component != (Object)null)
			{
				return Is173(component.gameObject);
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(Transform), "set_position")]
	internal static class Transform_set_position_SCP173_Patch
	{
		[HarmonyPrefix]
		private static bool Prefix(Transform __instance, ref Vector3 value)
		{
			//IL_000b: 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)
			if (!SCP173UnityProtectionPatches.Is173((Component)(object)__instance))
			{
				return true;
			}
			if (!Finite(value))
			{
				value = __instance.position;
			}
			return false;
		}

		private static bool Finite(Vector3 v)
		{
			//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)
			//IL_001a: 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_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			if (!float.IsNaN(v.x) && !float.IsNaN(v.y) && !float.IsNaN(v.z) && !float.IsInfinity(v.x) && !float.IsInfinity(v.y))
			{
				return !float.IsInfinity(v.z);
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(Transform), "set_rotation")]
	internal static class Transform_set_rotation_SCP173_Patch
	{
		[HarmonyPrefix]
		private static bool Prefix(Transform __instance, ref Quaternion value)
		{
			//IL_000b: 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)
			if (!SCP173UnityProtectionPatches.Is173((Component)(object)__instance))
			{
				return true;
			}
			if (!Finite(value))
			{
				value = __instance.rotation;
			}
			return false;
		}

		private static bool Finite(Quaternion q)
		{
			//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)
			//IL_001a: 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_0034: 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_004e: 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)
			if (!float.IsNaN(q.x) && !float.IsNaN(q.y) && !float.IsNaN(q.z) && !float.IsNaN(q.w) && !float.IsInfinity(q.x) && !float.IsInfinity(q.y) && !float.IsInfinity(q.z))
			{
				return !float.IsInfinity(q.w);
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(Transform), "set_localScale")]
	internal static class Transform_set_localScale_SCP173_Patch
	{
		[HarmonyPrefix]
		private static bool Prefix(Transform __instance, ref Vector3 value)
		{
			//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)
			if (!SCP173UnityProtectionPatches.Is173((Component)(object)__instance))
			{
				return true;
			}
			value = SCP173Runtime.ExpectedScale;
			return false;
		}
	}
	[HarmonyPatch(typeof(Transform), "SetPositionAndRotation")]
	internal static class Transform_SetPositionAndRotation_SCP173_Patch
	{
		[HarmonyPrefix]
		private static bool Prefix(Transform __instance)
		{
			return !SCP173UnityProtectionPatches.Is173((Component)(object)__instance);
		}
	}
	[HarmonyPatch(typeof(Transform), "set_localPosition")]
	internal static class Transform_set_localPosition_SCP173_Patch
	{
		[HarmonyPrefix]
		private static bool Prefix(Transform __instance)
		{
			return !SCP173UnityProtectionPatches.Is173((Component)(object)__instance);
		}
	}
	[HarmonyPatch(typeof(Transform), "set_localRotation")]
	internal static class Transform_set_localRotation_SCP173_Patch
	{
		[HarmonyPrefix]
		private static bool Prefix(Transform __instance)
		{
			return !SCP173UnityProtectionPatches.Is173((Component)(object)__instance);
		}
	}
	[HarmonyPatch(typeof(Transform), "SetParent", new Type[]
	{
		typeof(Transform),
		typeof(bool)
	})]
	internal static class Transform_SetParent_SCP173_Patch
	{
		[HarmonyPrefix]
		private static bool Prefix(Transform __instance)
		{
			return !SCP173UnityProtectionPatches.Is173((Component)(object)__instance);
		}
	}
	[HarmonyPatch(typeof(GameObject), "SetActive")]
	internal static class GameObject_SetActive_SCP173_Patch
	{
		[HarmonyPrefix]
		private static bool Prefix(GameObject __instance, bool value)
		{
			if (!SCP173UnityProtectionPatches.Is173(__instance))
			{
				return true;
			}
			return value;
		}
	}
	[HarmonyPatch(typeof(Behaviour), "set_enabled")]
	internal static class Behaviour_set_enabled_SCP173_Patch
	{
		[HarmonyPrefix]
		private static bool Prefix(Behaviour __instance, ref bool value)
		{
			if (!SCP173UnityProtectionPatches.Is173((Component)(object)__instance))
			{
				return true;
			}
			if (__instance is SCP173HazardController)
			{
				value = true;
			}
			else
			{
				value = __instance.enabled;
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(Renderer), "set_enabled")]
	internal static class Renderer_set_enabled_SCP173_Patch
	{
		[HarmonyPrefix]
		private static bool Prefix(Renderer __instance, ref bool value)
		{
			if (!SCP173UnityProtectionPatches.Is173((Component)(object)__instance))
			{
				return true;
			}
			value = true;
			return false;
		}
	}
	[HarmonyPatch(typeof(Renderer), "set_forceRenderingOff")]
	internal static class Renderer_set_forceRenderingOff_SCP173_Patch
	{
		[HarmonyPrefix]
		private static bool Prefix(Renderer __instance, ref bool value)
		{
			if (!SCP173UnityProtectionPatches.Is173((Component)(object)__instance))
			{
				return true;
			}
			value = false;
			return false;
		}
	}
	[HarmonyPatch(typeof(MeshFilter), "set_sharedMesh")]
	internal static class MeshFilter_set_sharedMesh_SCP173_Patch
	{
		[HarmonyPrefix]
		private static bool Prefix(MeshFilter __instance, ref Mesh value)
		{
			if (!SCP173UnityProtectionPatches.Is173((Component)(object)__instance))
			{
				return true;
			}
			value = SCP173Runtime.ExpectedMesh;
			return false;
		}
	}
	[HarmonyPatch(typeof(MeshCollider), "set_sharedMesh")]
	internal static class MeshCollider_set_sharedMesh_SCP173_Patch
	{
		[HarmonyPrefix]
		private static bool Prefix(MeshCollider __instance, ref Mesh value)
		{
			if (!SCP173UnityProtectionPatches.Is173((Component)(object)__instance))
			{
				return true;
			}
			value = SCP173Runtime.ExpectedMesh;
			return false;
		}
	}
	[HarmonyPatch(typeof(Renderer), "set_sharedMaterials")]
	internal static class MeshRenderer_set_sharedMaterials_SCP173_Patch
	{
		[HarmonyPrefix]
		private static bool Prefix(MeshRenderer __instance, ref Material[] value)
		{
			if (!SCP173UnityProtectionPatches.Is173((Component)(object)__instance))
			{
				return true;
			}
			Material expectedMaterial = SCP173Runtime.ExpectedMaterial;
			value = (Material[])(((Object)(object)expectedMaterial == (Object)null) ? ((Array)value) : ((Array)new Material[1] { expectedMaterial }));
			return false;
		}
	}
	[HarmonyPatch(typeof(Renderer), "set_sharedMaterial")]
	internal static class MeshRenderer_set_sharedMaterial_SCP173_Patch
	{
		[HarmonyPrefix]
		private static bool Prefix(MeshRenderer __instance, ref Material value)
		{
			if (!SCP173UnityProtectionPatches.Is173((Component)(object)__instance))
			{
				return true;
			}
			value = SCP173Runtime.ExpectedMaterial;
			return false;
		}
	}
	[HarmonyPatch(typeof(Renderer), "set_material")]
	internal static class Renderer_set_material_SCP173_Patch
	{
		[HarmonyPrefix]
		private static bool Prefix(Renderer __instance, ref Material value)
		{
			if (!SCP173UnityProtectionPatches.Is173((Component)(object)__instance))
			{
				return true;
			}
			value = SCP173Runtime.ExpectedMaterial;
			return false;
		}
	}
	[HarmonyPatch(typeof(GameObject), "AddComponent", new Type[] { typeof(Type) })]
	internal static class GameObject_AddComponent_SCP173_Patch
	{
		[HarmonyPrefix]
		private static bool Prefix(GameObject __instance, Type componentType)
		{
			if (!SCP173UnityProtectionPatches.Is173(__instance))
			{
				return true;
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(Collider), "set_enabled")]
	internal static class Collider_set_enabled_SCP173_Patch
	{
		[HarmonyPrefix]
		private static bool Prefix(Collider __instance, ref bool value)
		{
			if (!SCP173UnityProtectionPatches.Is173((Component)(object)__instance))
			{
				return true;
			}
			value = true;
			return false;
		}
	}
	[HarmonyPatch(typeof(Rigidbody), "set_isKinematic")]
	internal static class Rigidbody_set_isKinematic_SCP173_Patch
	{
		[HarmonyPrefix]
		private static bool Prefix(Rigidbody __instance, ref bool value)
		{
			if (!SCP173UnityProtectionPatches.Is173((Component)(object)__instance))
			{
				return true;
			}
			value = true;
			return false;
		}
	}
	[HarmonyPatch(typeof(Object), "Destroy", new Type[] { typeof(Object) })]
	internal static class Object_Destroy_SCP173_Patch
	{
		[HarmonyPrefix]
		private static bool Prefix(Object obj)
		{
			if (SCP173Runtime.InternalMutation)
			{
				return true;
			}
			if (!SCP173UnityProtectionPatches.Is173((Component)(object)((obj is Component) ? obj : null)))
			{
				return !SCP173UnityProtectionPatches.Is173((GameObject)(object)((obj is GameObject) ? obj : null));
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(Object), "DestroyImmediate", new Type[] { typeof(Object) })]
	internal static class Object_DestroyImmediate_SCP173_Patch
	{
		[HarmonyPrefix]
		private static bool Prefix(Object obj)
		{
			if (SCP173Runtime.InternalMutation)
			{
				return true;
			}
			if (!SCP173UnityProtectionPatches.Is173((Component)(object)((obj is Component) ? obj : null)))
			{
				return !SCP173UnityProtectionPatches.Is173((GameObject)(object)((obj is GameObject) ? obj : null));
			}
			return false;
		}
	}
	public static class UnitRegistry
	{
		private static readonly HashSet<Unit> s_liveUnits = new HashSet<Unit>();

		public static void Register(Unit unit)
		{
			if (!((Object)(object)unit == (Object)null) && !SCP173Runtime.IsReferenceProxy(unit))
			{
				s_liveUnits.Add(unit);
			}
		}

		public static void Unregister(Unit unit)
		{
			if (!((Object)(object)unit == (Object)null))
			{
				s_liveUnits.Remove(unit);
			}
		}

		public static void GetAllLivingUnits(List<Unit> buffer)
		{
			buffer.Clear();
			foreach (Unit s_liveUnit in s_liveUnits)
			{
				if ((Object)(object)s_liveUnit != (Object)null && !SCP173Runtime.IsReferenceProxy(s_liveUnit) && !SCP173Runtime.HasNeckBeenBroken(s_liveUnit) && !s_liveUnit.dead)
				{
					buffer.Add(s_liveUnit);
				}
			}
		}

		public static void Clear()
		{
			s_liveUnits.Clear();
		}
	}
	public static class WinAndProtectionPatches
	{
		[HarmonyPatch(typeof(Unit), "set_RuntimeReference")]
		private static class Unit_RuntimeReference_Patch
		{
			[HarmonyPostfix]
			private static void Postfix(Unit __instance)
			{
				if (DummyUnitFactory.IsDummy(__instance))
				{
					SCP173Runtime.BindReference(__instance);
				}
			}
		}

		[HarmonyPatch(typeof(Unit), "DestroyUnit")]
		private static class Unit_DestroyUnit_Patch
		{
			[HarmonyPrefix]
			private static bool Prefix(Unit __instance)
			{
				return !SCP173Runtime.IsProtectedUnit(__instance);
			}
		}

		[HarmonyPatch(typeof(HealthHandler), "TakeDamage")]
		private static class HealthHandler_TakeDamage_Patch
		{
			[HarmonyPrefix]
			private static bool Prefix(HealthHandler __instance)
			{
				return !SCP173Runtime.IsProtectedUnit(((Object)(object)__instance != (Object)null) ? ((Component)__instance).GetComponentInParent<Unit>() : null);
			}
		}

		[HarmonyPatch(typeof(HealthHandler), "Die", new Type[] { typeof(Unit) })]
		private static class HealthHandler_Die_Patch
		{
			[HarmonyPrefix]
			private static bool Prefix(HealthHandler __instance)
			{
				return !SCP173Runtime.IsProtectedUnit(((Object)(object)__instance != (Object)null) ? ((Component)__instance).GetComponentInParent<Unit>() : null);
			}
		}

		[HarmonyPatch(typeof(WinConditionPropagator), "OnUnitDied")]
		private static class WinConditionPropagator_OnUnitDied_Patch
		{
			[HarmonyPrefix]
			private static bool Prefix(Unit unit)
			{
				return !SCP173Runtime.IsProtectedUnit(unit);
			}
		}

		[HarmonyPatch(typeof(WinConditionPropagator), "IsUnitMustKill")]
		private static class WinConditionPropagator_IsUnitMustKill_Patch
		{
			[HarmonyPrefix]
			private static bool Prefix(Unit unit, ref WinCondition mustKillUnitWinCondition)
			{
				if (!SCP173Runtime.IsProtectedUnit(unit))
				{
					return true;
				}
				mustKillUnitWinCondition = null;
				return false;
			}
		}

		[HarmonyPatch(typeof(WinConditionEvaluator), "IsUnitMustKill")]
		private static class WinConditionEvaluator_IsUnitMustKill_Patch
		{
			[HarmonyPostfix]
			private static void Postfix(Unit unit, ref bool __result, ref WinCondition mustKillUnitWinCondition)
			{
				if (SCP173Runtime.IsProtectedUnit(unit))
				{
					__result = false;
					mustKillUnitWinCondition = null;
				}
			}
		}

		[HarmonyPatch(typeof(TeamSystem), "TriggerUnitDeathAction")]
		private static class TeamSystem_TriggerUnitDeathAction_Patch
		{
			[HarmonyPrefix]
			private static bool Prefix(Unit unit)
			{
				return !SCP173Runtime.IsProtectedUnit(unit);
			}
		}

		[HarmonyPatch(typeof(BaseGameMode), "DecideWinner")]
		private static class BaseGameMode_DecideWinner_Patch
		{
			[HarmonyPrefix]
			private static bool Prefix()
			{
				return !SCP173Runtime.HasSpawned;
			}
		}

		[HarmonyPatch(typeof(BaseGameMode), "OnWinnerDecided")]
		private static class BaseGameMode_OnWinnerDecided_Patch
		{
			[HarmonyPrefix]
			private static bool Prefix()
			{
				return !SCP173Runtime.HasSpawned;
			}
		}

		[HarmonyPatch(typeof(OnlineMultiplayerGameMode), "DecideWinner")]
		private static class Online_DecideWinner_Patch
		{
			[HarmonyPrefix]
			private static bool Prefix()
			{
				return !SCP173Runtime.HasSpawned;
			}
		}

		[HarmonyPatch(typeof(OnlineMultiplayerGameMode), "OnWinnerDecided")]
		private static class Online_OnWinnerDecided_Patch
		{
			[HarmonyPrefix]
			private static bool Prefix()
			{
				return !SCP173Runtime.HasSpawned;
			}
		}

		[HarmonyPatch(typeof(BaseGameMode), "set_MatchOver")]
		private static class BaseGameMode_MatchOverSetter_Patch
		{
			[HarmonyPrefix]
			private static bool Prefix(bool value)
			{
				if (value && SCP173Runtime.HasSpawned)
				{
					return false;
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(TimeService), "Pause")]
		private static class TimeService_Pause_Patch
		{
			[HarmonyPostfix]
			private static void Postfix()
			{
				SCP173Runtime.MarkTimeServiceTouched();
			}
		}

		[HarmonyPatch(typeof(TimeService), "UnPause")]
		private static class TimeService_UnPause_Patch
		{
			[HarmonyPostfix]
			private static void Postfix()
			{
				SCP173Runtime.MarkTimeServiceTouched();
			}
		}

		[HarmonyPatch(typeof(TimeService), "SetState", new Type[]
		{
			typeof(float),
			typeof(float),
			typeof(bool)
		})]
		private static class TimeService_SetState_Patch
		{
			[HarmonyPostfix]
			private static void Postfix()
			{
				SCP173Runtime.MarkTimeServiceTouched();
			}
		}
	}
}