Decompiled source of PropHunt v1.2.1

PropHunt/PropHunt.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ComputerysModdingUtilities;
using FishNet;
using FishNet.Broadcast;
using FishNet.Connection;
using FishNet.Managing;
using FishNet.Managing.Client;
using FishNet.Managing.Object;
using FishNet.Managing.Server;
using FishNet.Object;
using FishNet.Object.Synchronizing;
using FishNet.Serializing;
using FishNet.Transporting;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Steamworks;
using TMPro;
using Unity.Collections;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: StraftatMod(false)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[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 PropHunt
{
	internal static class Disguise
	{
		internal sealed class HiderSlot
		{
			internal int PlayerId;

			internal bool IsLocal;

			internal GameObject Clone;

			internal readonly List<Renderer> HiddenRenderers = new List<Renderer>();

			internal readonly List<Collider> HiddenColliders = new List<Collider>();

			internal PlayerHealth HiddenGraphicsOwner;

			internal readonly List<Mesh> OwnedMeshes = new List<Mesh>(4);

			internal readonly List<Material> OwnedMaterials = new List<Material>(8);

			internal bool CloneHitboxOk;

			internal bool CleanupPending;

			internal float CleanupPendingSince;

			internal float CleanupExtraSeconds;

			internal bool DeathHandled;
		}

		private enum MeshTier
		{
			None,
			SharedMesh,
			Asset,
			BatchExtract,
			ColliderProxy
		}

		private const float PickRange = 6f;

		private const int MaxAncestorHops = 4;

		private const string CloneName = "PropHunt_Disguise";

		private const string HitboxName = "PropHunt_Hitbox";

		private const int ShootableLayer = 11;

		private const string WalkBoxName = "PropHunt_WalkBox";

		private const int WalkableLayer = 14;

		private const string PartName = "PropHunt_Part";

		private const string DummyName = "PropHunt_WeaponDummy";

		private const string LightName = "PropHunt_SpawnerLight";

		private const string WalkColName = "PropHunt_WalkCollider";

		private const string ProbeAnchorName = "PropHunt_ProbeAnchor";

		private const string OutlineWidthProp = "_OutlineWidth";

		private const string RuntimeMeshPrefix = "PropHunt_";

		internal static readonly int PickMask = -2558413;

		private static readonly Dictionary<int, HiderSlot> _slots = new Dictionary<int, HiderSlot>(8);

		private static readonly List<HiderSlot> _slotList = new List<HiderSlot>(8);

		private static Dictionary<string, List<Mesh>> _assetMeshesByName;

		private static int _assetCacheSceneHandle;

		private static string _assetCacheSceneName;

		private static PropertyInfo _staticBatchRootProp;

		private static bool _staticBatchRootResolved;

		private static readonly RaycastHit[] _rayScratch = (RaycastHit[])(object)new RaycastHit[256];

		private const float SpatialFallbackRange = 0.75f;

		private const float MaxGroundSlack = 0.6f;

		private const float WallMountMaxGap = 0.1f;

		private const float WallProbeMargin = 0.3f;

		internal const float WallNormalMaxY = 0.35f;

		private const float PendingCleanupMaxSeconds = 10f;

		internal static List<HiderSlot> SlotList => _slotList;

		private static HiderSlot GetOrCreateSlot(int playerId)
		{
			if (_slots.TryGetValue(playerId, out var value))
			{
				return value;
			}
			value = new HiderSlot
			{
				PlayerId = playerId
			};
			_slots[playerId] = value;
			_slotList.Add(value);
			return value;
		}

		private static void RemoveSlot(HiderSlot slot)
		{
			_slots.Remove(slot.PlayerId);
			_slotList.Remove(slot);
		}

		internal static bool SlotHasLiveClone(int playerId)
		{
			if (_slots.TryGetValue(playerId, out var value))
			{
				return (Object)(object)value.Clone != (Object)null;
			}
			return false;
		}

		internal static bool RaycastNearestIgnoringRoot(Vector3 origin, Vector3 dir, float range, Transform ignoreRoot, out RaycastHit best, bool ignoreAllClones = false)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			best = default(RaycastHit);
			int num = Physics.RaycastNonAlloc(origin, dir, _rayScratch, range, PickMask, (QueryTriggerInteraction)1);
			float num2 = float.MaxValue;
			for (int i = 0; i < num; i++)
			{
				RaycastHit val = _rayScratch[i];
				if (!((Object)(object)((RaycastHit)(ref val)).collider == (Object)null) && !(((RaycastHit)(ref val)).distance >= num2) && (!((Object)(object)ignoreRoot != (Object)null) || !((Component)((RaycastHit)(ref val)).collider).transform.IsChildOf(ignoreRoot)) && (!ignoreAllClones || !IsUnderClone(((Component)((RaycastHit)(ref val)).collider).transform)))
				{
					best = val;
					num2 = ((RaycastHit)(ref val)).distance;
				}
			}
			return num2 < float.MaxValue;
		}

		internal static bool SphereCastNearestIgnoringRoot(Vector3 origin, float radius, Vector3 dir, float range, Transform ignoreRoot, out float distance)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			distance = 0f;
			int num = Physics.SphereCastNonAlloc(origin, radius, dir, _rayScratch, range, PickMask, (QueryTriggerInteraction)1);
			float num2 = float.MaxValue;
			for (int i = 0; i < num; i++)
			{
				RaycastHit val = _rayScratch[i];
				if (!((Object)(object)((RaycastHit)(ref val)).collider == (Object)null) && !(((RaycastHit)(ref val)).distance >= num2) && (!((Object)(object)ignoreRoot != (Object)null) || !((Component)((RaycastHit)(ref val)).collider).transform.IsChildOf(ignoreRoot)))
				{
					num2 = ((RaycastHit)(ref val)).distance;
				}
			}
			if (num2 == float.MaxValue)
			{
				return false;
			}
			distance = num2;
			return true;
		}

		internal static bool IsUnderClone(Transform t)
		{
			if ((Object)(object)t == (Object)null)
			{
				return false;
			}
			for (int i = 0; i < _slotList.Count; i++)
			{
				GameObject clone = _slotList[i].Clone;
				if ((Object)(object)clone != (Object)null && t.IsChildOf(clone.transform))
				{
					return true;
				}
			}
			return false;
		}

		internal static bool TryPick(FirstPersonController fpc, out string path, out string meshName, out Vector3 lossyScale, out int spawnerObjectId, out string fail)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: 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_007a: 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)
			path = null;
			meshName = null;
			lossyScale = Vector3.one;
			spawnerObjectId = -1;
			fail = "internal error";
			try
			{
				Camera playerCamera = fpc.playerCamera;
				if ((Object)(object)playerCamera == (Object)null)
				{
					fail = "no camera";
					return PickFail(fail);
				}
				GameObject val;
				if (!RaycastNearestIgnoringRoot(((Component)playerCamera).transform.position, ((Component)playerCamera).transform.forward, 6f, ((Component)fpc).transform.root, out var best, ignoreAllClones: true))
				{
					val = RayMissFallback(((Component)playerCamera).transform.position, ((Component)playerCamera).transform.forward);
					if ((Object)(object)val == (Object)null)
					{
						fail = "nothing in range (6 m)";
						PickFail(fail);
						fail = "Nothing there to disguise as.";
						return false;
					}
				}
				else
				{
					val = ChooseCandidate(best, out fail);
					if ((Object)(object)val == (Object)null)
					{
						PickFail(fail);
						fail = FriendlyPickFail(fail);
						return false;
					}
				}
				if (!TryRecoverRenderMesh(val, out var mesh, out var _, out var meshKey, out var ownsMesh, out fail))
				{
					Plugin.Activity("Disguise: pick '" + ((Object)val).name + "' failed mesh recovery - " + fail);
					return false;
				}
				if (ownsMesh && (Object)(object)mesh != (Object)null)
				{
					Object.Destroy((Object)(object)mesh);
				}
				try
				{
					ItemSpawner componentInParent = val.GetComponentInParent<ItemSpawner>();
					if ((Object)(object)componentInParent != (Object)null && (Object)(object)((NetworkBehaviour)componentInParent).NetworkObject != (Object)null)
					{
						spawnerObjectId = ((NetworkBehaviour)componentInParent).NetworkObject.ObjectId;
						Plugin.Activity($"Disguise: pick resolved spawner '{((Object)componentInParent).name}' (ObjectId {spawnerObjectId}).");
					}
				}
				catch (Exception e)
				{
					Plugin.LogOnce("Disguise.SpawnerDetect", e);
					spawnerObjectId = -1;
				}
				path = BuildScenePath(val.transform);
				meshName = meshKey;
				lossyScale = val.transform.lossyScale;
				return true;
			}
			catch (Exception e2)
			{
				Plugin.LogOnce("Disguise.TryPick", e2);
				fail = "error (see log)";
				return false;
			}
		}

		private static bool PickFail(string fail)
		{
			Plugin.Activity("Disguise: pick failed - " + fail);
			return false;
		}

		private static string FriendlyPickFail(string fail)
		{
			try
			{
				if (fail == null || !fail.StartsWith("too big (", StringComparison.Ordinal) || !fail.EndsWith(" m)", StringComparison.Ordinal))
				{
					return fail;
				}
				if (float.TryParse(fail.Substring("too big (".Length, fail.Length - "too big (".Length - " m)".Length), out var result) && result > 50f)
				{
					return "That's part of the map - try a smaller object.";
				}
				return fail;
			}
			catch (Exception e)
			{
				Plugin.LogOnce("Disguise.FriendlyFail", e);
				return fail;
			}
		}

		private static GameObject ChooseCandidate(RaycastHit hit, out string fail)
		{
			//IL_0328: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0220: Unknown result type (might be due to invalid IL or missing references)
			//IL_022e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0233: Unknown result type (might be due to invalid IL or missing references)
			//IL_0235: Unknown result type (might be due to invalid IL or missing references)
			//IL_023c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0244: Unknown result type (might be due to invalid IL or missing references)
			fail = "that's not a solid prop";
			try
			{
				HashSet<GameObject> hashSet = new HashSet<GameObject>();
				List<GameObject> list = new List<GameObject>(16);
				Transform val = ((Component)((RaycastHit)(ref hit)).collider).transform;
				int num = 0;
				while (num <= 4 && (Object)(object)val != (Object)null)
				{
					if (hashSet.Add(((Component)val).gameObject))
					{
						list.Add(((Component)val).gameObject);
					}
					num++;
					val = val.parent;
				}
				MeshFilter[] componentsInChildren = ((Component)((RaycastHit)(ref hit)).collider).GetComponentsInChildren<MeshFilter>(true);
				foreach (MeshFilter val2 in componentsInChildren)
				{
					if ((Object)(object)val2 != (Object)null && hashSet.Add(((Component)val2).gameObject))
					{
						list.Add(((Component)val2).gameObject);
					}
				}
				GameObject val3 = null;
				float num2 = -1f;
				string strB = null;
				GameObject val4 = null;
				float num3 = float.MaxValue;
				string text = null;
				float num4 = float.MaxValue;
				int num5 = 0;
				int num6 = 0;
				foreach (GameObject item in list)
				{
					MeshFilter component = item.GetComponent<MeshFilter>();
					if ((Object)(object)component == (Object)null || (Object)(object)component.sharedMesh == (Object)null || ((Object)item).name == "PropHunt_Disguise" || IsUnderClone(item.transform))
					{
						continue;
					}
					MeshRenderer component2 = item.GetComponent<MeshRenderer>();
					if ((Object)(object)component2 == (Object)null)
					{
						continue;
					}
					if (!((Renderer)component2).enabled || !item.activeInHierarchy)
					{
						if (num5 < 12)
						{
							num5++;
							Plugin.Activity("Disguise: pick candidate '" + ((Object)item).name + "' skipped - not visible.");
						}
						else
						{
							num6++;
						}
						continue;
					}
					Bounds bounds = ((Renderer)component2).bounds;
					float num7 = Vector3.Distance(((RaycastHit)(ref hit)).point, ((Bounds)(ref bounds)).ClosestPoint(((RaycastHit)(ref hit)).point));
					if (!ValidateSource(item, out var fail2))
					{
						if (num5 < 12)
						{
							num5++;
							Plugin.Activity("Disguise: pick candidate '" + ((Object)item).name + "' rejected - " + fail2);
						}
						else
						{
							num6++;
						}
						if (num7 < num4)
						{
							num4 = num7;
							text = fail2;
						}
						continue;
					}
					Bounds val5 = bounds;
					((Bounds)(ref val5)).Expand(0.6f);
					if (((Bounds)(ref val5)).Contains(((RaycastHit)(ref hit)).point))
					{
						Vector3 size = ((Bounds)(ref bounds)).size;
						float num8 = size.x * size.y * size.z;
						string text2 = BuildScenePath(item.transform);
						if ((Object)(object)val3 == (Object)null || num8 > num2 || (num8 == num2 && string.CompareOrdinal(text2, strB) < 0))
						{
							val3 = item;
							num2 = num8;
							strB = text2;
						}
					}
					else if (num7 < num3)
					{
						val4 = item;
						num3 = num7;
					}
				}
				if (num6 > 0)
				{
					Plugin.Activity($"Disguise: {num6} more candidate rejections suppressed (large subtree).");
				}
				if ((Object)(object)val3 != (Object)null)
				{
					Plugin.Activity($"Disguise: pick chose '{((Object)val3).name}' (contains hit, vol {num2:0.###})");
					return val3;
				}
				if ((Object)(object)val4 != (Object)null)
				{
					Plugin.Activity($"Disguise: pick chose '{((Object)val4).name}' (nearest to hit, {num3:0.##} m)");
					return val4;
				}
				GameObject val6 = SpatialFallback(((RaycastHit)(ref hit)).point);
				if ((Object)(object)val6 != (Object)null)
				{
					return val6;
				}
				if (text != null)
				{
					fail = text;
				}
				return null;
			}
			catch (Exception e)
			{
				Plugin.LogOnce("Disguise.ChooseCandidate", e);
				return null;
			}
		}

		private static GameObject SpatialFallback(Vector3 hitPoint)
		{
			//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)
			try
			{
				float bestSqrOut;
				GameObject val = ScanNearestValidRenderer((Bounds b) => ((Bounds)(ref b)).SqrDistance(hitPoint), 0.5625f, out bestSqrOut);
				if ((Object)(object)val != (Object)null)
				{
					Plugin.Activity($"Disguise: spatial fallback chose '{((Object)val).name}' (dist {Mathf.Sqrt(bestSqrOut):0.00})");
				}
				return val;
			}
			catch (Exception e)
			{
				Plugin.LogOnce("Disguise.SpatialFallback", e);
				return null;
			}
		}

		private static GameObject RayMissFallback(Vector3 origin, Vector3 dir)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				float bestSqrOut;
				GameObject val = ScanNearestValidRenderer(delegate(Bounds b)
				{
					//IL_0002: Unknown result type (might be due to invalid IL or missing references)
					//IL_0008: Unknown result type (might be due to invalid IL or missing references)
					//IL_000d: Unknown result type (might be due to invalid IL or missing references)
					//IL_0013: Unknown result type (might be due to invalid IL or missing references)
					//IL_0030: Unknown result type (might be due to invalid IL or missing references)
					//IL_0036: Unknown result type (might be due to invalid IL or missing references)
					//IL_003c: Unknown result type (might be due to invalid IL or missing references)
					//IL_0041: Unknown result type (might be due to invalid IL or missing references)
					float num = Mathf.Clamp(Vector3.Dot(((Bounds)(ref b)).center - origin, dir), 0f, 6f);
					return ((Bounds)(ref b)).SqrDistance(origin + dir * num);
				}, 0.5625f, out bestSqrOut);
				if ((Object)(object)val != (Object)null)
				{
					Plugin.Activity($"Disguise: pick ray-miss fallback chose '{((Object)val).name}' (dist {Mathf.Sqrt(bestSqrOut):0.00})");
				}
				return val;
			}
			catch (Exception e)
			{
				Plugin.LogOnce("Disguise.RayMissFallback", e);
				return null;
			}
		}

		private static GameObject ScanNearestValidRenderer(Func<Bounds, float> sqrDistOf, float maxSqr, out float bestSqrOut)
		{
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = null;
			float num = float.MaxValue;
			string text = null;
			MeshRenderer[] array = Object.FindObjectsOfType<MeshRenderer>();
			foreach (MeshRenderer val2 in array)
			{
				if ((Object)(object)val2 == (Object)null || !((Renderer)val2).enabled)
				{
					continue;
				}
				GameObject gameObject = ((Component)val2).gameObject;
				if (!gameObject.activeInHierarchy || ((Object)gameObject).name == "PropHunt_Disguise" || IsUnderClone(gameObject.transform))
				{
					continue;
				}
				MeshFilter component = gameObject.GetComponent<MeshFilter>();
				if ((Object)(object)component == (Object)null || (Object)(object)component.sharedMesh == (Object)null)
				{
					continue;
				}
				float num2 = sqrDistOf(((Renderer)val2).bounds);
				if (num2 > maxSqr || num2 > num || !ValidateSource(gameObject, out var _))
				{
					continue;
				}
				if (num2 < num)
				{
					val = gameObject;
					num = num2;
					text = null;
					continue;
				}
				if (text == null)
				{
					text = BuildScenePath(val.transform);
				}
				string text2 = BuildScenePath(gameObject.transform);
				if (string.CompareOrdinal(text2, text) < 0)
				{
					val = gameObject;
					text = text2;
				}
			}
			bestSqrOut = num;
			return val;
		}

		private static bool ValidateSource(GameObject go, out string fail)
		{
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			fail = null;
			if ((Object)(object)go.GetComponentInParent<ItemBehaviour>() != (Object)null)
			{
				fail = "that's a weapon/item";
				return false;
			}
			if ((Object)(object)go.GetComponentInParent<PlayerHealth>() != (Object)null)
			{
				fail = "that's a player";
				return false;
			}
			string name = ((Object)go).name;
			switch (name)
			{
			case "PROC_PLANE":
			case "SKINNED_PROC_PLANE":
			case "GlassGib":
			case "Bullet Hole":
				fail = "that's combat debris";
				Plugin.Activity("Disguise: leftover excluded '" + name + "' (debris GO name).");
				return false;
			default:
			{
				string name2 = ((Object)go.transform.root).name;
				if (name2.EndsWith("(Clone)", StringComparison.Ordinal))
				{
					fail = "that's combat debris";
					Plugin.Activity("Disguise: leftover excluded '" + name + "' (runtime-spawned root '" + name2 + "').");
					return false;
				}
				if ((Object)(object)go.GetComponent<WFX_BulletHoleDecal>() != (Object)null)
				{
					fail = "that's combat debris";
					Plugin.Activity("Disguise: leftover excluded '" + name + "' (bullet-hole decal).");
					return false;
				}
				if ((Object)(object)go.GetComponentInParent<BodyParts>() != (Object)null)
				{
					fail = "that's combat debris";
					Plugin.Activity("Disguise: leftover excluded '" + name + "' (dismemberment gib).");
					return false;
				}
				NetworkObject componentInParent = go.GetComponentInParent<NetworkObject>();
				if ((Object)(object)componentInParent != (Object)null && !componentInParent.IsSceneObject)
				{
					fail = "that's a networked object";
					return false;
				}
				if (go.tag == "vfx" || go.tag == "Hat")
				{
					fail = "that's not a solid prop";
					return false;
				}
				MeshRenderer component = go.GetComponent<MeshRenderer>();
				if ((Object)(object)component == (Object)null)
				{
					fail = "that's not a solid prop";
					return false;
				}
				Bounds bounds = ((Renderer)component).bounds;
				Vector3 size = ((Bounds)(ref bounds)).size;
				float num = Mathf.Max(size.x, Mathf.Max(size.y, size.z));
				float value = Plugin.CfgMinPropSize.Value;
				float value2 = Plugin.CfgMaxPropSize.Value;
				if (num < value)
				{
					fail = $"too small ({num:0.0} m)";
					return false;
				}
				if (num > value2)
				{
					fail = $"too big ({num:0.0} m)";
					return false;
				}
				return true;
			}
			}
		}

		private static string BuildScenePath(Transform t)
		{
			StringBuilder stringBuilder = new StringBuilder(128);
			BuildScenePathInto(stringBuilder, t);
			return stringBuilder.ToString();
		}

		private static void BuildScenePathInto(StringBuilder sb, Transform t)
		{
			if ((Object)(object)t.parent != (Object)null)
			{
				BuildScenePathInto(sb, t.parent);
				sb.Append('/');
			}
			sb.Append(((Object)t).name);
		}

		internal static bool TryRecoverRenderMesh(GameObject go, out Mesh mesh, out Material[] materials, out string meshKey, out bool ownsMesh, out string fail)
		{
			mesh = null;
			materials = null;
			meshKey = null;
			ownsMesh = false;
			fail = "that prop can't be copied - pick a movable one";
			MeshFilter component = go.GetComponent<MeshFilter>();
			MeshRenderer component2 = go.GetComponent<MeshRenderer>();
			if ((Object)(object)component == (Object)null || (Object)(object)component.sharedMesh == (Object)null || (Object)(object)component2 == (Object)null)
			{
				return false;
			}
			Mesh assetMesh;
			MeshTier meshTier = DecideTier(go, component, component2, out assetMesh);
			meshKey = KeyForTier(go, component, meshTier);
			switch (meshTier)
			{
			case MeshTier.SharedMesh:
				mesh = component.sharedMesh;
				materials = ((Renderer)component2).sharedMaterials;
				Plugin.Activity("Disguise: tier A (sharedMesh) serves '" + ((Object)go).name + "'.");
				return true;
			case MeshTier.Asset:
				mesh = assetMesh;
				materials = ((Renderer)component2).sharedMaterials;
				Plugin.Activity("Disguise: tier ASSET ('" + ((Object)assetMesh).name + "') serves '" + ((Object)go).name + "'.");
				return true;
			case MeshTier.BatchExtract:
				try
				{
					if (TryExtractSubMeshes(go, component2, component.sharedMesh, out mesh))
					{
						materials = ((Renderer)component2).sharedMaterials;
						ownsMesh = true;
						Plugin.Activity("Disguise: tier C (batch extract) serves '" + ((Object)go).name + "'.");
						return true;
					}
				}
				catch (Exception e)
				{
					Plugin.LogOnce("Disguise.TierCExtract", e);
					mesh = null;
				}
				break;
			default:
				meshKey = null;
				return false;
			case MeshTier.ColliderProxy:
				break;
			}
			MeshCollider component3 = go.GetComponent<MeshCollider>();
			if ((Object)(object)component3 != (Object)null && (Object)(object)component3.sharedMesh != (Object)null && ColliderMeshLooksRenderable(go, component3, component2))
			{
				mesh = component3.sharedMesh;
				materials = ((Renderer)component2).sharedMaterials;
				Plugin.Activity("Disguise: tier B (collider proxy) serves '" + ((Object)go).name + "'.");
				return true;
			}
			meshKey = null;
			mesh = null;
			return false;
		}

		private static MeshTier DecideTier(GameObject go, MeshFilter mf, MeshRenderer mr, out Mesh assetMesh)
		{
			assetMesh = null;
			if (!((Renderer)mr).isPartOfStaticBatch)
			{
				return MeshTier.SharedMesh;
			}
			if (TryFindAssetMesh(go, mr, out assetMesh))
			{
				return MeshTier.Asset;
			}
			if (mf.sharedMesh.isReadable)
			{
				return MeshTier.BatchExtract;
			}
			MeshCollider component = go.GetComponent<MeshCollider>();
			if ((Object)(object)component != (Object)null && (Object)(object)component.sharedMesh != (Object)null)
			{
				return MeshTier.ColliderProxy;
			}
			return MeshTier.None;
		}

		private static string KeyForTier(GameObject go, MeshFilter mf, MeshTier tier)
		{
			switch (tier)
			{
			case MeshTier.SharedMesh:
				return ((Object)mf.sharedMesh).name;
			case MeshTier.Asset:
				return "asset:" + BaseAssetName(((Object)go).name);
			case MeshTier.BatchExtract:
				return "batch:" + ((Object)mf.sharedMesh).name;
			case MeshTier.ColliderProxy:
			{
				MeshCollider component = go.GetComponent<MeshCollider>();
				if (!((Object)(object)component != (Object)null) || !((Object)(object)component.sharedMesh != (Object)null))
				{
					return null;
				}
				return "col:" + ((Object)component.sharedMesh).name;
			}
			default:
				return null;
			}
		}

		private static bool ColliderMeshLooksRenderable(GameObject go, MeshCollider mc, MeshRenderer mr)
		{
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: 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_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				string text = (((Object)mc.sharedMesh).name ?? "").ToLowerInvariant();
				if (text.Contains("collider") || text.Contains("collision") || text.Contains("ucx") || text.Contains("phys"))
				{
					return false;
				}
				Bounds bounds = mc.sharedMesh.bounds;
				Vector3 val = Vector3.Scale(((Bounds)(ref bounds)).size, go.transform.lossyScale);
				float magnitude = ((Vector3)(ref val)).magnitude;
				bounds = ((Renderer)mr).bounds;
				val = ((Bounds)(ref bounds)).size;
				float magnitude2 = ((Vector3)(ref val)).magnitude;
				if (magnitude < 0.0001f || magnitude2 < 0.0001f)
				{
					return false;
				}
				float num = magnitude2 / magnitude;
				return num >= 0.75f && num <= 1.35f;
			}
			catch (Exception e)
			{
				Plugin.LogOnce("Disguise.TierBGate", e);
				return false;
			}
		}

		private static string GetMeshKey(GameObject go)
		{
			MeshFilter component = go.GetComponent<MeshFilter>();
			MeshRenderer component2 = go.GetComponent<MeshRenderer>();
			if ((Object)(object)component == (Object)null || (Object)(object)component.sharedMesh == (Object)null || (Object)(object)component2 == (Object)null)
			{
				return null;
			}
			Mesh assetMesh;
			return KeyForTier(go, component, DecideTier(go, component, component2, out assetMesh));
		}

		private static bool TryFindAssetMesh(GameObject go, MeshRenderer mr, out Mesh mesh)
		{
			mesh = null;
			try
			{
				string text = BaseAssetName(((Object)go).name);
				if (string.IsNullOrEmpty(text))
				{
					return false;
				}
				Dictionary<string, List<Mesh>> assetMeshCache = GetAssetMeshCache();
				if (assetMeshCache == null || !assetMeshCache.TryGetValue(text, out var value) || value == null)
				{
					return false;
				}
				foreach (Mesh item in value)
				{
					if (!((Object)(object)item == (Object)null) && AssetMeshMatchesRenderer(item, go, mr))
					{
						mesh = item;
						return true;
					}
				}
				return false;
			}
			catch (Exception e)
			{
				Plugin.LogOnce("Disguise.AssetLookup", e);
				return false;
			}
		}

		private static string BaseAssetName(string goName)
		{
			if (goName == null)
			{
				return null;
			}
			string text = goName.Trim();
			bool flag = true;
			while (flag && text.Length > 0)
			{
				flag = false;
				if (text.EndsWith("(Clone)", StringComparison.Ordinal))
				{
					text = text.Substring(0, text.Length - "(Clone)".Length).TrimEnd(Array.Empty<char>());
					flag = true;
				}
				else
				{
					if (text[text.Length - 1] != ')')
					{
						continue;
					}
					int num = text.LastIndexOf('(');
					if (num <= 0 || text[num - 1] != ' ' || num + 1 >= text.Length - 1)
					{
						continue;
					}
					bool flag2 = true;
					for (int i = num + 1; i < text.Length - 1; i++)
					{
						if (!char.IsDigit(text[i]))
						{
							flag2 = false;
							break;
						}
					}
					if (flag2)
					{
						text = text.Substring(0, num - 1).TrimEnd(Array.Empty<char>());
						flag = true;
					}
				}
			}
			return text;
		}

		private static Dictionary<string, List<Mesh>> GetAssetMeshCache()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			Scene activeScene = SceneManager.GetActiveScene();
			int handle = ((Scene)(ref activeScene)).handle;
			string name = ((Scene)(ref activeScene)).name;
			if (_assetMeshesByName != null && handle == _assetCacheSceneHandle && name == _assetCacheSceneName)
			{
				return _assetMeshesByName;
			}
			Dictionary<string, List<Mesh>> dictionary = new Dictionary<string, List<Mesh>>(512, StringComparer.Ordinal);
			Mesh[] array = Resources.FindObjectsOfTypeAll<Mesh>();
			foreach (Mesh val in array)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				string name2 = ((Object)val).name;
				if (!string.IsNullOrEmpty(name2) && !name2.StartsWith("PropHunt_", StringComparison.Ordinal))
				{
					if (!dictionary.TryGetValue(name2, out var value))
					{
						value = (dictionary[name2] = new List<Mesh>(1));
					}
					value.Add(val);
				}
			}
			foreach (List<Mesh> value2 in dictionary.Values)
			{
				if (value2.Count > 1)
				{
					value2.Sort(CompareAssetMeshes);
				}
			}
			_assetMeshesByName = dictionary;
			_assetCacheSceneHandle = handle;
			_assetCacheSceneName = name;
			Plugin.Activity($"Disguise: asset mesh cache built ({dictionary.Count} names).");
			return dictionary;
		}

		private static int CompareAssetMeshes(Mesh a, Mesh b)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			bool flag = (Object)(object)a == (Object)null;
			bool flag2 = (Object)(object)b == (Object)null;
			if (flag || flag2)
			{
				if (flag != flag2)
				{
					if (!flag)
					{
						return -1;
					}
					return 1;
				}
				return 0;
			}
			int num = a.vertexCount.CompareTo(b.vertexCount);
			if (num == 0)
			{
				Bounds bounds = a.bounds;
				Vector3 size = ((Bounds)(ref bounds)).size;
				float sqrMagnitude = ((Vector3)(ref size)).sqrMagnitude;
				bounds = b.bounds;
				size = ((Bounds)(ref bounds)).size;
				return sqrMagnitude.CompareTo(((Vector3)(ref size)).sqrMagnitude);
			}
			return num;
		}

		private static bool AssetMeshMatchesRenderer(Mesh mesh, GameObject go, MeshRenderer mr)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			Bounds val = TransformBounds(go.transform.localToWorldMatrix, mesh.bounds);
			Vector3 size = ((Bounds)(ref val)).size;
			Bounds bounds = ((Renderer)mr).bounds;
			Vector3 size2 = ((Bounds)(ref bounds)).size;
			for (int i = 0; i < 3; i++)
			{
				if (((Vector3)(ref size))[i] < 0.0001f || ((Vector3)(ref size2))[i] < 0.0001f)
				{
					return false;
				}
				float num = ((Vector3)(ref size2))[i] / ((Vector3)(ref size))[i];
				if (num < 0.85f || num > 1.18f)
				{
					return false;
				}
			}
			return true;
		}

		private static bool TryExtractSubMeshes(GameObject go, MeshRenderer mr, Mesh combined, out Mesh extracted)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: 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_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_024b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0250: Unknown result type (might be due to invalid IL or missing references)
			//IL_0252: Unknown result type (might be due to invalid IL or missing references)
			//IL_0254: Unknown result type (might be due to invalid IL or missing references)
			//IL_0256: Unknown result type (might be due to invalid IL or missing references)
			//IL_025b: Unknown result type (might be due to invalid IL or missing references)
			//IL_025f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0264: Unknown result type (might be due to invalid IL or missing references)
			//IL_0268: Unknown result type (might be due to invalid IL or missing references)
			//IL_026d: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d7: Expected O, but got Unknown
			//IL_0326: Unknown result type (might be due to invalid IL or missing references)
			//IL_032b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0330: Unknown result type (might be due to invalid IL or missing references)
			//IL_0344: Unknown result type (might be due to invalid IL or missing references)
			//IL_0349: Unknown result type (might be due to invalid IL or missing references)
			//IL_034e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0383: Unknown result type (might be due to invalid IL or missing references)
			//IL_036b: Unknown result type (might be due to invalid IL or missing references)
			//IL_036f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0364: Unknown result type (might be due to invalid IL or missing references)
			//IL_0397: Unknown result type (might be due to invalid IL or missing references)
			//IL_044c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0451: Unknown result type (might be due to invalid IL or missing references)
			//IL_0453: Unknown result type (might be due to invalid IL or missing references)
			//IL_0465: Unknown result type (might be due to invalid IL or missing references)
			extracted = null;
			Material[] sharedMaterials = ((Renderer)mr).sharedMaterials;
			int num = ((sharedMaterials != null) ? sharedMaterials.Length : 0);
			int subMeshCount = combined.subMeshCount;
			if (num <= 0 || subMeshCount < num)
			{
				return false;
			}
			Transform staticBatchRoot = GetStaticBatchRoot((Renderer)(object)mr);
			Matrix4x4 val = (((Object)(object)staticBatchRoot != (Object)null) ? staticBatchRoot.localToWorldMatrix : Matrix4x4.identity);
			Bounds bounds = ((Renderer)mr).bounds;
			int num2 = -1;
			float num3 = float.MaxValue;
			float num4 = float.MaxValue;
			for (int i = 0; i + num <= subMeshCount; i++)
			{
				Bounds val2 = default(Bounds);
				for (int j = 0; j < num; j++)
				{
					SubMeshDescriptor subMesh = combined.GetSubMesh(i + j);
					Bounds val3 = TransformBounds(val, ((SubMeshDescriptor)(ref subMesh)).bounds);
					if (j == 0)
					{
						val2 = val3;
					}
					else
					{
						((Bounds)(ref val2)).Encapsulate(val3);
					}
				}
				Vector3 val4 = ((Bounds)(ref val2)).center - ((Bounds)(ref bounds)).center;
				Vector3 val5 = ((Bounds)(ref val2)).size - ((Bounds)(ref bounds)).size;
				float num5 = Mathf.Abs(val4.x) + Mathf.Abs(val4.y) + Mathf.Abs(val4.z) + Mathf.Abs(val5.x) + Mathf.Abs(val5.y) + Mathf.Abs(val5.z);
				if (num5 < num3)
				{
					num4 = num3;
					num3 = num5;
					num2 = i;
				}
				else if (num5 < num4)
				{
					num4 = num5;
				}
			}
			Vector3 size = ((Bounds)(ref bounds)).size;
			float num6 = 0.05f * Mathf.Max(1f, ((Vector3)(ref size)).magnitude);
			bool flag = num4 == float.MaxValue || (num4 >= 2f * num3 && num4 > 0f);
			if (num2 < 0 || num3 >= num6 || !flag)
			{
				Plugin.Activity("Disguise: batched submesh match rejected for '" + ((Object)go).name + "' " + $"(best {num3:0.###}, second {num4:0.###}, tol {num6:0.###}).");
				return false;
			}
			Vector3[] vertices = combined.vertices;
			Vector3[] normals = combined.normals;
			Vector2[] uv = combined.uv;
			Vector2[] uv2 = combined.uv2;
			bool flag2 = normals != null && normals.Length == combined.vertexCount;
			bool flag3 = uv != null && uv.Length == combined.vertexCount;
			bool flag4 = uv2 != null && uv2.Length == combined.vertexCount;
			Matrix4x4 worldToLocalMatrix = go.transform.worldToLocalMatrix;
			Matrix4x4 val6 = worldToLocalMatrix * val;
			val6 = ((Matrix4x4)(ref val6)).inverse;
			Matrix4x4 transpose = ((Matrix4x4)(ref val6)).transpose;
			int[] array = new int[combined.vertexCount];
			for (int k = 0; k < array.Length; k++)
			{
				array[k] = -1;
			}
			List<Vector3> list = new List<Vector3>();
			List<Vector3> list2 = (flag2 ? new List<Vector3>() : null);
			List<Vector2> list3 = (flag3 ? new List<Vector2>() : null);
			List<Vector2> list4 = (flag4 ? new List<Vector2>() : null);
			List<int[]> list5 = new List<int[]>(num);
			for (int l = 0; l < num; l++)
			{
				int[] indices = combined.GetIndices(num2 + l);
				int[] array2 = new int[indices.Length];
				for (int m = 0; m < indices.Length; m++)
				{
					int num7 = indices[m];
					int num8 = array[num7];
					if (num8 < 0)
					{
						num8 = (array[num7] = list.Count);
						list.Add(((Matrix4x4)(ref worldToLocalMatrix)).MultiplyPoint3x4(((Matrix4x4)(ref val)).MultiplyPoint3x4(vertices[num7])));
						if (flag2)
						{
							Vector3 val7 = ((Matrix4x4)(ref transpose)).MultiplyVector(normals[num7]);
							float magnitude = ((Vector3)(ref val7)).magnitude;
							list2.Add((magnitude > 0.0001f) ? (val7 / magnitude) : Vector3.up);
						}
						if (flag3)
						{
							list3.Add(uv[num7]);
						}
						if (flag4)
						{
							list4.Add(uv2[num7]);
						}
					}
					array2[m] = num8;
				}
				list5.Add(array2);
			}
			Mesh val8 = new Mesh();
			try
			{
				((Object)val8).name = "PropHunt_Extract_" + ((Object)go).name;
				if (list.Count > 65534)
				{
					val8.indexFormat = (IndexFormat)1;
				}
				val8.SetVertices(list);
				if (flag2)
				{
					val8.SetNormals(list2);
				}
				if (flag3)
				{
					val8.SetUVs(0, list3);
				}
				if (flag4)
				{
					val8.SetUVs(1, list4);
				}
				val8.subMeshCount = num;
				bool flag5 = true;
				for (int n = 0; n < num; n++)
				{
					MeshTopology topology = combined.GetTopology(num2 + n);
					if ((int)topology != 0)
					{
						flag5 = false;
					}
					val8.SetIndices(list5[n], topology, n);
				}
				if (!flag2 && flag5)
				{
					val8.RecalculateNormals();
				}
				if (flag3 && flag5)
				{
					val8.RecalculateTangents();
				}
				val8.RecalculateBounds();
			}
			catch
			{
				Object.Destroy((Object)(object)val8);
				throw;
			}
			extracted = val8;
			return true;
		}

		private static Bounds TransformBounds(Matrix4x4 m, Bounds b)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: 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_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = ((Matrix4x4)(ref m)).MultiplyPoint3x4(((Bounds)(ref b)).center);
			Vector3 extents = ((Bounds)(ref b)).extents;
			Vector3 val2 = default(Vector3);
			((Vector3)(ref val2))..ctor(Mathf.Abs(m.m00) * extents.x + Mathf.Abs(m.m01) * extents.y + Mathf.Abs(m.m02) * extents.z, Mathf.Abs(m.m10) * extents.x + Mathf.Abs(m.m11) * extents.y + Mathf.Abs(m.m12) * extents.z, Mathf.Abs(m.m20) * extents.x + Mathf.Abs(m.m21) * extents.y + Mathf.Abs(m.m22) * extents.z);
			return new Bounds(val, val2 * 2f);
		}

		private static Transform GetStaticBatchRoot(Renderer r)
		{
			if (!_staticBatchRootResolved)
			{
				_staticBatchRootResolved = true;
				try
				{
					_staticBatchRootProp = typeof(Renderer).GetProperty("staticBatchRootTransform", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				}
				catch
				{
					_staticBatchRootProp = null;
				}
			}
			if (_staticBatchRootProp == null)
			{
				return null;
			}
			try
			{
				object? value = _staticBatchRootProp.GetValue(r, null);
				return (Transform)((value is Transform) ? value : null);
			}
			catch
			{
				return null;
			}
		}

		internal static bool ApplyFromMessage(PropHuntNet msg, bool logResolutionFailure = true)
		{
			//IL_0271: Unknown result type (might be due to invalid IL or missing references)
			//IL_0276: Unknown result type (might be due to invalid IL or missing references)
			//IL_0278: Unknown result type (might be due to invalid IL or missing references)
			//IL_027b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0280: Unknown result type (might be due to invalid IL or missing references)
			//IL_0285: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02be: Unknown result type (might be due to invalid IL or missing references)
			HiderSlot hiderSlot = null;
			try
			{
				if (!Plugin.CfgEnabled.Value)
				{
					return true;
				}
				PropHuntManager instance = PropHuntManager.Instance;
				if ((Object)(object)instance == (Object)null)
				{
					return true;
				}
				int a = msg.A;
				int num = PropHuntManager.ConnIdForPlayer(a);
				if (num < 0)
				{
					if (logResolutionFailure)
					{
						Plugin.Activity($"Disguise: op-4 for unknown PlayerId {a} - ignored.");
					}
					return false;
				}
				PlayerHealth val = instance.FindHealthByConn(num);
				if ((Object)(object)val != (Object)null && !instance.IsBindableHealth(val))
				{
					if (logResolutionFailure)
					{
						Plugin.Log.LogWarning((object)$"Disguise: player object for prop {a} is stale/despawning - that hider stays visible.");
					}
					return false;
				}
				if ((Object)(object)val == (Object)null)
				{
					if (logResolutionFailure)
					{
						Plugin.Log.LogWarning((object)$"Disguise: player object for prop {a} not found - that hider stays visible.");
					}
					return false;
				}
				hiderSlot = GetOrCreateSlot(a);
				hiderSlot.IsLocal = PropHuntManager.LocalRole == Role.Hider && a == PropHuntManager.LocalPlayerId();
				string text = msg.S ?? "";
				int num2 = text.IndexOf('\n');
				string text2 = ((num2 >= 0) ? text.Substring(0, num2) : text);
				string text3 = ((num2 >= 0) ? text.Substring(num2 + 1) : "");
				GameObject val2 = ResolveByPath(text2);
				if ((Object)(object)val2 != (Object)null && !HasRenderMesh(val2))
				{
					val2 = null;
				}
				if ((Object)(object)val2 != (Object)null && !string.IsNullOrEmpty(text3))
				{
					string meshKey = GetMeshKey(val2);
					if (meshKey == null || meshKey != text3)
					{
						Plugin.Log.LogWarning((object)("Disguise: path '" + text2 + "' resolved mesh key '" + (meshKey ?? "<none>") + "' instead of '" + text3 + "' - falling back to mesh search."));
						val2 = null;
					}
				}
				if ((Object)(object)val2 == (Object)null && !string.IsNullOrEmpty(text3))
				{
					val2 = FindUniqueByMeshName(text3);
				}
				ItemSpawner val3 = ((msg.B > 0) ? ResolveSpawner(msg.B - 1, val2) : null);
				if ((Object)(object)val2 == (Object)null && (Object)(object)val3 == (Object)null)
				{
					Plugin.Log.LogWarning((object)("Disguise: couldn't resolve prop '" + text2 + "' (mesh '" + text3 + "') - hider stays visible."));
					return true;
				}
				if ((Object)(object)val2 != (Object)null)
				{
					Vector3 lossyScale = val2.transform.lossyScale;
					Vector3 val4 = lossyScale - msg.V;
					if (((Vector3)(ref val4)).sqrMagnitude > 0.01f * Mathf.Max(0.01f, ((Vector3)(ref msg.V)).sqrMagnitude))
					{
						Plugin.Log.LogWarning((object)$"Disguise: resolved scale {lossyScale} differs from sender's {msg.V} - possible mismatched resolution.");
					}
				}
				DestroyClone(hiderSlot);
				bool isLocal = hiderSlot.IsLocal;
				if (!isLocal || Plugin.CfgShowOwnProp.Value)
				{
					bool flag = false;
					if ((Object)(object)val3 != (Object)null)
					{
						flag = BuildCloneSpawner(hiderSlot, val, val3);
						if (!flag && (Object)(object)val2 != (Object)null)
						{
							Plugin.Log.LogWarning((object)("Disguise: spawner composite failed for '" + ((Object)val3).name + "' - plain prop fallback."));
							flag = BuildClone(hiderSlot, val, val2);
						}
					}
					else
					{
						flag = BuildClone(hiderSlot, val, val2);
					}
					if (!flag)
					{
						RestoreGraphics(hiderSlot);
						return true;
					}
				}
				HideGraphics(hiderSlot, val);
				if (hiderSlot.CloneHitboxOk)
				{
					HideHitboxColliders(hiderSlot, val);
				}
				else
				{
					RestoreHiddenColliders(hiderSlot);
				}
				if (isLocal)
				{
					PropHuntManager.ClientDisguisedThisTake = true;
				}
				Plugin.Activity($"Disguise: applied '{(((Object)(object)val3 != (Object)null) ? ((Object)val3).name : ((Object)val2).name)}' onto prop {a}.");
				return true;
			}
			catch (Exception e)
			{
				Plugin.LogOnce("Disguise.Apply", e);
				try
				{
					if (hiderSlot != null)
					{
						CleanupSlot(hiderSlot);
					}
				}
				catch
				{
				}
				return true;
			}
		}

		private static bool HasRenderMesh(GameObject go)
		{
			MeshFilter component = go.GetComponent<MeshFilter>();
			if ((Object)(object)component != (Object)null && (Object)(object)component.sharedMesh != (Object)null)
			{
				return (Object)(object)go.GetComponent<MeshRenderer>() != (Object)null;
			}
			return false;
		}

		private static GameObject ResolveByPath(string path)
		{
			//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)
			if (string.IsNullOrEmpty(path))
			{
				return null;
			}
			string[] array = path.Split(new char[1] { '/' });
			for (int i = 0; i < SceneManager.sceneCount; i++)
			{
				Scene sceneAt = SceneManager.GetSceneAt(i);
				if (!((Scene)(ref sceneAt)).isLoaded)
				{
					continue;
				}
				GameObject[] rootGameObjects = ((Scene)(ref sceneAt)).GetRootGameObjects();
				foreach (GameObject val in rootGameObjects)
				{
					if (((Object)val).name != array[0])
					{
						continue;
					}
					Transform val2 = val.transform;
					bool flag = true;
					for (int k = 1; k < array.Length; k++)
					{
						val2 = val2.Find(array[k]);
						if ((Object)(object)val2 == (Object)null)
						{
							flag = false;
							break;
						}
					}
					if (flag)
					{
						return ((Component)val2).gameObject;
					}
				}
			}
			return null;
		}

		private static GameObject FindUniqueByMeshName(string meshKey)
		{
			GameObject result = null;
			int num = 0;
			MeshFilter[] array = Object.FindObjectsOfType<MeshFilter>(true);
			foreach (MeshFilter val in array)
			{
				if ((Object)(object)val == (Object)null || (Object)(object)val.sharedMesh == (Object)null)
				{
					continue;
				}
				GameObject gameObject = ((Component)val).gameObject;
				if (!(((Object)gameObject).name == "PropHunt_Disguise") && !IsUnderClone(gameObject.transform) && !((Object)(object)gameObject.GetComponent<MeshRenderer>() == (Object)null) && !(GetMeshKey(gameObject) != meshKey) && ValidateSource(gameObject, out var _))
				{
					result = gameObject;
					num++;
					if (num > 1)
					{
						return null;
					}
				}
			}
			if (num != 1)
			{
				return null;
			}
			return result;
		}

		private static bool BuildClone(HiderSlot slot, PlayerHealth hiderPh, GameObject source)
		{
			//IL_0326: Unknown result type (might be due to invalid IL or missing references)
			//IL_032b: Unknown result type (might be due to invalid IL or missing references)
			//IL_032f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0335: Unknown result type (might be due to invalid IL or missing references)
			//IL_033a: Unknown result type (might be due to invalid IL or missing references)
			//IL_033e: Unknown result type (might be due to invalid IL or missing references)
			//IL_035e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0360: Unknown result type (might be due to invalid IL or missing references)
			//IL_0367: Unknown result type (might be due to invalid IL or missing references)
			//IL_0369: Unknown result type (might be due to invalid IL or missing references)
			//IL_039d: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bd: 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_00c9: Expected O, but got Unknown
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: 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_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Unknown result type (might be due to invalid IL or missing references)
			//IL_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0216: Unknown result type (might be due to invalid IL or missing references)
			//IL_0222: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			//IL_0241: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: Unknown result type (might be due to invalid IL or missing references)
			//IL_025d: Unknown result type (might be due to invalid IL or missing references)
			//IL_026c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0273: Expected O, but got Unknown
			//IL_02a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c3: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				MeshRenderer component = source.GetComponent<MeshRenderer>();
				if ((Object)(object)component == (Object)null)
				{
					return false;
				}
				if (!TryRecoverRenderMesh(source, out var mesh, out var materials, out var _, out var ownsMesh, out var fail))
				{
					Plugin.Log.LogWarning((object)("Disguise: mesh recovery failed for '" + ((Object)source).name + "' (" + fail + ") - hider stays visible."));
					return false;
				}
				if (ownsMesh)
				{
					slot.OwnedMeshes.Add(mesh);
				}
				PropLighting.LogSceneInventoryOnce();
				float num = ComputeGroundSlack(source, component, ((Component)hiderPh).transform);
				if (num > 0.01f)
				{
					Plugin.Activity($"Disguise: ground slack for '{((Object)source).name}' = {num:0.00}m");
				}
				Transform transform = ((Component)hiderPh).transform;
				GameObject val = (slot.Clone = new GameObject("PropHunt_Disguise"));
				val.transform.SetParent(transform, false);
				val.AddComponent<MeshFilter>().sharedMesh = mesh;
				MeshRenderer val2 = val.AddComponent<MeshRenderer>();
				((Renderer)val2).sharedMaterials = materials;
				((Renderer)val2).shadowCastingMode = ((Renderer)component).shadowCastingMode;
				((Renderer)val2).receiveShadows = ((Renderer)component).receiveShadows;
				Vector3 lossyScale = transform.lossyScale;
				Vector3 lossyScale2 = source.transform.lossyScale;
				val.transform.localScale = new Vector3(SafeDiv(lossyScale2.x, lossyScale.x), SafeDiv(lossyScale2.y, lossyScale.y), SafeDiv(lossyScale2.z, lossyScale.z));
				Quaternion val3 = YawOnly(transform.rotation);
				Quaternion val4 = Quaternion.Inverse(val3) * source.transform.rotation;
				val.transform.rotation = val3 * val4;
				val.transform.position = transform.position;
				CharacterController component2 = ((Component)hiderPh).GetComponent<CharacterController>();
				float y;
				Bounds bounds;
				if (!((Object)(object)component2 != (Object)null))
				{
					y = transform.position.y;
				}
				else
				{
					bounds = ((Collider)component2).bounds;
					y = ((Bounds)(ref bounds)).min.y;
				}
				float num2 = y;
				Bounds bounds2 = ((Renderer)val2).bounds;
				Transform transform2 = val.transform;
				transform2.position += new Vector3(transform.position.x - ((Bounds)(ref bounds2)).center.x, num2 - num - ((Bounds)(ref bounds2)).min.y, transform.position.z - ((Bounds)(ref bounds2)).center.z);
				try
				{
					GameObject val5 = new GameObject("PropHunt_Hitbox");
					val5.layer = 11;
					val5.transform.SetParent(val.transform, false);
					BoxCollider val6 = val5.AddComponent<BoxCollider>();
					((Collider)val6).isTrigger = false;
					bounds = mesh.bounds;
					val6.center = ((Bounds)(ref bounds)).center;
					bounds = mesh.bounds;
					val6.size = ((Bounds)(ref bounds)).size;
					if ((Object)(object)component2 != (Object)null)
					{
						Physics.IgnoreCollision((Collider)(object)val6, (Collider)(object)component2, true);
					}
					if (HitboxResolvesHider(val5, hiderPh))
					{
						slot.CloneHitboxOk = true;
					}
					else
					{
						Plugin.Log.LogWarning((object)"Disguise: prop hitbox wouldn't resolve the hider's PlayerHealth - keeping the humanoid hitbox.");
						Object.Destroy((Object)(object)val5);
					}
				}
				catch (Exception e)
				{
					Plugin.LogOnce("Disguise.Hitbox", e);
					slot.CloneHitboxOk = false;
				}
				bounds = mesh.bounds;
				Vector3 center = ((Bounds)(ref bounds)).center;
				bounds = mesh.bounds;
				AddWalkBox(val, center, ((Bounds)(ref bounds)).size, component2);
				DisguiseFollower disguiseFollower = val.AddComponent<DisguiseFollower>();
				disguiseFollower.Root = transform;
				disguiseFollower.DeltaRot = val4;
				disguiseFollower.SrcLossyScale = lossyScale2;
				disguiseFollower.Cc = component2;
				disguiseFollower.GraphicsT = ResolveGraphicsAnchor(hiderPh);
				disguiseFollower.CloneMr = val2;
				disguiseFollower.GroundSlack = num;
				if (ComputeWallMount(source.transform, ((Renderer)component).bounds, transform, out var backLocal, out var gap, out var halfExtent))
				{
					disguiseFollower.WallMounted = true;
					disguiseFollower.WallBackLocal = backLocal;
					disguiseFollower.WallGap = gap;
					disguiseFollower.WallHalfExtent = halfExtent;
				}
				disguiseFollower.SetManualYaw(disguiseFollower.SeedYaw = ((Quaternion)(ref val3)).eulerAngles.y);
				disguiseFollower.SlotPlayerId = slot.PlayerId;
				if (slot.IsLocal)
				{
					disguiseFollower.IsLocalHider = true;
					disguiseFollower.Fpc = ((Component)hiderPh).GetComponent<FirstPersonController>();
				}
				return true;
			}
			catch (Exception e2)
			{
				Plugin.LogOnce("Disguise.BuildClone", e2);
				DestroyClone(slot);
				return false;
			}
		}

		private static bool HitboxResolvesHider(GameObject hitboxGo, PlayerHealth hiderPh)
		{
			PlayerHealth val = null;
			Transform root = hitboxGo.transform.root;
			if (((Component)root).CompareTag("Player"))
			{
				((Component)root).TryGetComponent<PlayerHealth>(ref val);
			}
			else
			{
				val = hitboxGo.GetComponentInParent<PlayerHealth>();
			}
			return (Object)(object)val == (Object)(object)hiderPh;
		}

		private static void AddWalkBox(GameObject clone, Vector3 localCenter, Vector3 localSize, CharacterController hiderCc)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = null;
			try
			{
				if (Plugin.CfgSolidProps.Value)
				{
					val = new GameObject("PropHunt_WalkBox");
					val.layer = 14;
					val.transform.SetParent(clone.transform, false);
					BoxCollider val2 = val.AddComponent<BoxCollider>();
					((Collider)val2).isTrigger = false;
					val2.center = localCenter;
					val2.size = localSize;
					if ((Object)(object)hiderCc != (Object)null)
					{
						Physics.IgnoreCollision((Collider)(object)val2, (Collider)(object)hiderCc, true);
					}
				}
			}
			catch (Exception e)
			{
				Plugin.LogOnce("Disguise.WalkBox", e);
				if ((Object)(object)val != (Object)null)
				{
					try
					{
						Object.Destroy((Object)(object)val);
						return;
					}
					catch
					{
						return;
					}
				}
			}
		}

		private static ItemSpawner ResolveSpawner(int objectId, GameObject source)
		{
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				NetworkObject value = null;
				NetworkManager networkManager = InstanceFinder.NetworkManager;
				if ((Object)(object)networkManager != (Object)null)
				{
					if ((Object)(object)networkManager.ClientManager != (Object)null && networkManager.ClientManager.Objects != null)
					{
						((ManagedObjects)networkManager.ClientManager.Objects).Spawned.TryGetValue(objectId, out value);
					}
					if ((Object)(object)value == (Object)null && networkManager.IsServer && (Object)(object)networkManager.ServerManager != (Object)null && networkManager.ServerManager.Objects != null)
					{
						((ManagedObjects)networkManager.ServerManager.Objects).Spawned.TryGetValue(objectId, out value);
					}
				}
				if ((Object)(object)value != (Object)null)
				{
					ItemSpawner component = ((Component)value).GetComponent<ItemSpawner>();
					if ((Object)(object)component != (Object)null)
					{
						return component;
					}
				}
				Plugin.Log.LogWarning((object)$"Disguise: spawner ObjectId {objectId} didn't resolve - trying nearest spawner.");
				if ((Object)(object)source != (Object)null)
				{
					Vector3 position = source.transform.position;
					ItemSpawner val = null;
					float num = 1f;
					ItemSpawner[] array = Object.FindObjectsOfType<ItemSpawner>();
					foreach (ItemSpawner val2 in array)
					{
						if (!((Object)(object)val2 == (Object)null))
						{
							Vector3 val3 = ((Component)val2).transform.position - position;
							float sqrMagnitude = ((Vector3)(ref val3)).sqrMagnitude;
							if (sqrMagnitude < num)
							{
								val = val2;
								num = sqrMagnitude;
							}
						}
					}
					if ((Object)(object)val != (Object)null)
					{
						Plugin.Activity($"Disguise: nearest-spawner fallback chose '{((Object)val).name}' ({Mathf.Sqrt(num):0.00} m).");
						return val;
					}
				}
				Plugin.Log.LogWarning((object)"Disguise: spawner resolution failed entirely - plain prop fallback.");
				return null;
			}
			catch (Exception e)
			{
				Plugin.LogOnce("Disguise.ResolveSpawner", e);
				return null;
			}
		}

		private static bool BuildCloneSpawner(HiderSlot slot, PlayerHealth hiderPh, ItemSpawner spawner)
		{
			//IL_05e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_05fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_06af: Unknown result type (might be due to invalid IL or missing references)
			//IL_06b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_06b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_06ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_06e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0878: Unknown result type (might be due to invalid IL or missing references)
			//IL_087a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0881: Unknown result type (might be due to invalid IL or missing references)
			//IL_0883: Unknown result type (might be due to invalid IL or missing references)
			//IL_088a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0701: Unknown result type (might be due to invalid IL or missing references)
			//IL_0703: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0748: Unknown result type (might be due to invalid IL or missing references)
			//IL_074d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_075f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0780: Unknown result type (might be due to invalid IL or missing references)
			//IL_079c: Unknown result type (might be due to invalid IL or missing references)
			//IL_07bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_07d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_07f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_07fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0808: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Expected O, but got Unknown
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_021b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0225: Unknown result type (might be due to invalid IL or missing references)
			//IL_022a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0233: Unknown result type (might be due to invalid IL or missing references)
			//IL_0238: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0304: Unknown result type (might be due to invalid IL or missing references)
			//IL_0309: Unknown result type (might be due to invalid IL or missing references)
			//IL_0315: Unknown result type (might be due to invalid IL or missing references)
			//IL_031a: Unknown result type (might be due to invalid IL or missing references)
			//IL_031c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0322: Unknown result type (might be due to invalid IL or missing references)
			//IL_0329: Unknown result type (might be due to invalid IL or missing references)
			//IL_0335: Unknown result type (might be due to invalid IL or missing references)
			//IL_033c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0348: Unknown result type (might be due to invalid IL or missing references)
			//IL_034f: Unknown result type (might be due to invalid IL or missing references)
			//IL_035b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0365: Unknown result type (might be due to invalid IL or missing references)
			//IL_0386: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0467: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0490: Unknown result type (might be due to invalid IL or missing references)
			//IL_0495: Unknown result type (might be due to invalid IL or missing references)
			//IL_0499: Unknown result type (might be due to invalid IL or missing references)
			//IL_0482: Unknown result type (might be due to invalid IL or missing references)
			//IL_03db: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_04fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_050b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0518: Unknown result type (might be due to invalid IL or missing references)
			//IL_0524: Unknown result type (might be due to invalid IL or missing references)
			//IL_052f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0534: Unknown result type (might be due to invalid IL or missing references)
			//IL_0546: Unknown result type (might be due to invalid IL or missing references)
			//IL_054d: Expected O, but got Unknown
			//IL_057f: Unknown result type (might be due to invalid IL or missing references)
			//IL_058d: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Transform transform = ((Component)spawner).transform;
				List<MeshRenderer> list = new List<MeshRenderer>(8);
				MeshRenderer[] componentsInChildren = ((Component)transform).GetComponentsInChildren<MeshRenderer>(false);
				foreach (MeshRenderer val in componentsInChildren)
				{
					if (!((Object)(object)val == (Object)null) && ((Renderer)val).enabled)
					{
						GameObject gameObject = ((Component)val).gameObject;
						MeshFilter component = gameObject.GetComponent<MeshFilter>();
						if (!((Object)(object)component == (Object)null) && !((Object)(object)component.sharedMesh == (Object)null) && !((Object)(object)gameObject.GetComponentInParent<ItemBehaviour>() != (Object)null) && !AnyAncestorOnLayer(gameObject.transform, transform, 7, 8))
						{
							list.Add(val);
						}
					}
				}
				if (list.Count == 0)
				{
					Plugin.Log.LogWarning((object)("Disguise: spawner '" + ((Object)spawner).name + "' has no usable pedestal renderer."));
					return false;
				}
				PropLighting.LogSceneInventoryOnce();
				Bounds bounds = ((Renderer)list[0]).bounds;
				for (int j = 1; j < list.Count; j++)
				{
					((Bounds)(ref bounds)).Encapsulate(((Renderer)list[j]).bounds);
				}
				float num = ComputeSpawnerBurial(transform, bounds, ((Component)hiderPh).transform);
				if (num > 0.01f)
				{
					Plugin.Activity($"Disguise: spawner burial for '{((Object)spawner).name}' = {num:0.00}m");
				}
				Transform transform2 = ((Component)hiderPh).transform;
				GameObject val2 = (slot.Clone = new GameObject("PropHunt_Disguise"));
				val2.transform.SetParent(transform2, false);
				Vector3 lossyScale = transform2.lossyScale;
				Vector3 lossyScale2 = transform.lossyScale;
				val2.transform.localScale = new Vector3(SafeDiv(lossyScale2.x, lossyScale.x), SafeDiv(lossyScale2.y, lossyScale.y), SafeDiv(lossyScale2.z, lossyScale.z));
				Quaternion val3 = YawOnly(transform2.rotation);
				Quaternion val4 = Quaternion.Inverse(val3) * transform.rotation;
				val2.transform.rotation = val3 * val4;
				val2.transform.position = transform2.position;
				List<MeshRenderer> list2 = new List<MeshRenderer>(list.Count);
				MeshRenderer val5 = null;
				float num2 = -1f;
				Bounds localBase = default(Bounds);
				bool flag = false;
				Matrix4x4 worldToLocalMatrix = transform.worldToLocalMatrix;
				Vector3 lossyScale3 = val2.transform.lossyScale;
				Bounds bounds2;
				foreach (MeshRenderer item in list)
				{
					if (!TryRecoverRenderMesh(((Component)item).gameObject, out var mesh, out var materials, out var _, out var ownsMesh, out var fail))
					{
						Plugin.Activity("Disguise: spawner part '" + ((Object)((Component)item).gameObject).name + "' skipped - " + fail);
						continue;
					}
					if (ownsMesh)
					{
						slot.OwnedMeshes.Add(mesh);
					}
					Transform transform3 = ((Component)item).transform;
					GameObject val6 = new GameObject("PropHunt_Part")
					{
						layer = ((Component)item).gameObject.layer
					};
					val6.transform.SetParent(val2.transform, false);
					val6.transform.localPosition = ((Matrix4x4)(ref worldToLocalMatrix)).MultiplyPoint3x4(transform3.position);
					val6.transform.localRotation = Quaternion.Inverse(transform.rotation) * transform3.rotation;
					Vector3 lossyScale4 = transform3.lossyScale;
					val6.transform.localScale = new Vector3(SafeDiv(lossyScale4.x, lossyScale3.x), SafeDiv(lossyScale4.y, lossyScale3.y), SafeDiv(lossyScale4.z, lossyScale3.z));
					val6.AddComponent<MeshFilter>().sharedMesh = mesh;
					MeshRenderer val7 = val6.AddComponent<MeshRenderer>();
					((Renderer)val7).sharedMaterials = materials;
					((Renderer)val7).shadowCastingMode = ((Renderer)item).shadowCastingMode;
					((Renderer)val7).receiveShadows = ((Renderer)item).receiveShadows;
					list2.Add(val7);
					Bounds val8 = TransformBounds(worldToLocalMatrix * transform3.localToWorldMatrix, mesh.bounds);
					if (!flag)
					{
						localBase = val8;
						flag = true;
					}
					else
					{
						((Bounds)(ref localBase)).Encapsulate(val8);
					}
					bounds2 = ((Renderer)item).bounds;
					Vector3 size = ((Bounds)(ref bounds2)).size;
					float num3 = size.x * size.y * size.z;
					if (num3 > num2)
					{
						num2 = num3;
						val5 = val7;
					}
				}
				if (list2.Count == 0)
				{
					Plugin.Log.LogWarning((object)("Disguise: every pedestal part of '" + ((Object)spawner).name + "' failed mesh recovery."));
					DestroyClone(slot);
					return false;
				}
				CopySpawnerLights(val2, transform, worldToLocalMatrix);
				CharacterController component2 = ((Component)hiderPh).GetComponent<CharacterController>();
				float y;
				if (!((Object)(object)component2 != (Object)null))
				{
					y = transform2.position.y;
				}
				else
				{
					bounds2 = ((Collider)component2).bounds;
					y = ((Bounds)(ref bounds2)).min.y;
				}
				float num4 = y;
				Bounds bounds3 = ((Renderer)list2[0]).bounds;
				for (int k = 1; k < list2.Count; k++)
				{
					((Bounds)(ref bounds3)).Encapsulate(((Renderer)list2[k]).bounds);
				}
				Transform transform4 = val2.transform;
				transform4.position += new Vector3(transform2.position.x - ((Bounds)(ref bounds3)).center.x, num4 - num - ((Bounds)(ref bounds3)).min.y, transform2.position.z - ((Bounds)(ref bounds3)).center.z);
				bool flag2 = false;
				try
				{
					GameObject val9 = new GameObject("PropHunt_Hitbox");
					val9.layer = 11;
					val9.transform.SetParent(val2.transform, false);
					BoxCollider val10 = val9.AddComponent<BoxCollider>();
					((Collider)val10).isTrigger = false;
					val10.center = ((Bounds)(ref localBase)).center;
					val10.size = ((Bounds)(ref localBase)).size;
					if ((Object)(object)component2 != (Object)null)
					{
						Physics.IgnoreCollision((Collider)(object)val10, (Collider)(object)component2, true);
					}
					if (HitboxResolvesHider(val9, hiderPh))
					{
						flag2 = true;
					}
					else
					{
						Plugin.Log.LogWarning((object)"Disguise: spawner base hitbox wouldn't resolve the hider - keeping the humanoid hitbox.");
						Object.Destroy((Object)(object)val9);
					}
				}
				catch (Exception e)
				{
					Plugin.LogOnce("Disguise.SpawnerHitbox", e);
				}
				AddSpawnerWalkColliders(val2, transform, localBase, component2);
				Transform dummyT = null;
				Vector3 bobBase = Vector3.zero;
				Vector3 bobOffset = Vector3.zero;
				List<MeshRenderer> list3 = new List<MeshRenderer>(list2);
				bool flag3 = true;
				try
				{
					ItemBehaviour val11 = null;
					ItemBehaviour[] componentsInChildren2 = ((Component)transform).GetComponentsInChildren<ItemBehaviour>(false);
					foreach (ItemBehaviour val12 in componentsInChildren2)
					{
						if ((Object)(object)val12 != (Object)null && (Object)(object)val12.rootObject == (Object)null && !val12.isTaken)
						{
							val11 = val12;
							break;
						}
					}
					if ((Object)(object)val11 != (Object)null)
					{
						flag3 = BuildWeaponDummy(slot, val2, transform, val11, hiderPh, component2, list3, out dummyT, out bobBase, out bobOffset);
					}
				}
				catch (Exception e2)
				{
					Plugin.LogOnce("Disguise.WeaponDummy", e2);
					dummyT = null;
				}
				slot.CloneHitboxOk = flag2 && flag3;
				DisguiseFollower disguiseFollower = val2.AddComponent<DisguiseFollower>();
				disguiseFollower.Root = transform2;
				disguiseFollower.DeltaRot = val4;
				disguiseFollower.SrcLossyScale = lossyScale2;
				disguiseFollower.Cc = component2;
				disguiseFollower.GraphicsT = ResolveGraphicsAnchor(hiderPh);
				disguiseFollower.CloneMr = val5;
				disguiseFollower.GroundSlack = num;
				if (ComputeWallMount(transform, bounds, transform2, out var backLocal, out var gap, out var halfExtent))
				{
					disguiseFollower.WallMounted = true;
					disguiseFollower.WallBackLocal = backLocal;
					disguiseFollower.WallGap = gap;
					disguiseFollower.WallHalfExtent = halfExtent;
				}
				disguiseFollower.BoundsRenderers = list2.ToArray();
				list3.Remove(val5);
				disguiseFollower.ExtraLitRenderers = list3.ToArray();
				try
				{
					Bounds bounds4 = ((Renderer)list2[0]).bounds;
					for (int l = 1; l < list2.Count; l++)
					{
						((Bounds)(ref bounds4)).Encapsulate(((Renderer)list2[l]).bounds);
					}
					float num5 = num4;
					float num6 = Mathf.Max(((Bounds)(ref bounds4)).min.y, num5);
					float num7 = Mathf.Max(0.5f * (num6 + ((Bounds)(ref bounds4)).max.y), num5 + 0.15f);
					num7 = Mathf.Min(num7, ((Bounds)(ref bounds4)).max.y);
					Transform transform5 = new GameObject("PropHunt_ProbeAnchor").transform;
					transform5.SetParent(val2.transform, false);
					transform5.position = new Vector3(transform2.position.x, num7, transform2.position.z);
					((Renderer)val5).probeAnchor = transform5;
					for (int m = 0; m < list3.Count; m++)
					{
						if ((Object)(object)list3[m] != (Object)null)
						{
							((Renderer)list3[m]).probeAnchor = transform5;
						}
					}
					disguiseFollower.ProbeAnchorT = transform5;
				}
				catch (Exception e3)
				{
					Plugin.LogOnce("Disguise.ProbeAnchor", e3);
				}
				disguiseFollower.DummyT = dummyT;
				disguiseFollower.DummyBobBase = bobBase;
				disguiseFollower.DummyBobOffset = bobOffset;
				disguiseFollower.SetManualYaw(disguiseFollower.SeedYaw = ((Quaternion)(ref val3)).eulerAngles.y);
				disguiseFollower.SlotPlayerId = slot.PlayerId;
				if (slot.IsLocal)
				{
					disguiseFollower.IsLocalHider = true;
					disguiseFollower.Fpc = ((Component)hiderPh).GetComponent<FirstPersonController>();
				}
				Plugin.Activity($"Disguise: spawner composite built ({list2.Count} parts, " + $"dummy={(Object)(object)dummyT != (Object)null}, burial {num:0.00}m).");
				return true;
			}
			catch (Exception e4)
			{
				Plugin.LogOnce("Disguise.BuildSpawner", e4);
				DestroyClone(slot);
				return false;
			}
		}

		private static bool BuildWeaponDummy(HiderSlot slot, GameObject clone, Transform spawnerT, ItemBehaviour sitting, PlayerHealth hiderPh, CharacterController cc, List<MeshRenderer> extraLit, out Transform dummyT, out Vector3 bobBase, out Vector3 bobOffset)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Expected O, but got Unknown
			//IL_0098: 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_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0361: Unknown result type (might be due to invalid IL or missing references)
			//IL_0368: Expected O, but got Unknown
			//IL_0399: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01de: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0216: Unknown result type (might be due to invalid IL or missing references)
			//IL_0222: Unknown result type (might be due to invalid IL or missing references)
			//IL_0229: Unknown result type (might be due to invalid IL or missing references)
			//IL_0235: Unknown result type (might be due to invalid IL or missing references)
			//IL_023f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0270: Unknown result type (might be due to invalid IL or missing references)
			//IL_0291: Unknown result type (might be due to invalid IL or missing references)
			//IL_029a: Unknown result type (might be due to invalid IL or missing references)
			//IL_029f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bd: Unknown result type (might be due to invalid IL or missing references)
			dummyT = null;
			Transform transform = ((Component)sitting).transform;
			bobBase = spawnerT.InverseTransformPoint(spawnerT.position + Vector3.up * 0.5f);
			try
			{
				if (Reflect.ItemBobBaseField != null && (Object)(object)transform.parent == (Object)(object)spawnerT)
				{
					bobBase = (Vector3)Reflect.ItemBobBaseField.GetValue(sitting);
				}
			}
			catch (Exception e)
			{
				Plugin.LogOnce("Disguise.BobBase", e);
			}
			bobOffset = spawnerT.up * 0.5f;
			GameObject val = new GameObject("PropHunt_WeaponDummy");
			Bounds val2 = default(Bounds);
			try
			{
				val.transform.SetParent(clone.transform, false);
				val.transform.localPosition = bobBase;
				val.transform.localRotation = Quaternion.Inverse(spawnerT.rotation) * transform.rotation;
				val.transform.localScale = transform.localScale;
				Matrix4x4 worldToLocalMatrix = transform.worldToLocalMatrix;
				Vector3 lossyScale = val.transform.lossyScale;
				bool flag = false;
				int num = 0;
				MeshRenderer[] componentsInChildren = ((Component)transform).GetComponentsInChildren<MeshRenderer>(false);
				foreach (MeshRenderer val3 in componentsInChildren)
				{
					if ((Object)(object)val3 == (Object)null || !((Renderer)val3).enabled)
					{
						continue;
					}
					GameObject gameObject = ((Component)val3).gameObject;
					if (gameObject.tag == "vfx")
					{
						continue;
					}
					MeshFilter component = gameObject.GetComponent<MeshFilter>();
					if (!((Object)(object)component == (Object)null) && !((Object)(object)component.sharedMesh == (Object)null))
					{
						GameObject val4 = new GameObject("PropHunt_Part");
						val4.transform.SetParent(val.transform, false);
						val4.transform.localPosition = ((Matrix4x4)(ref worldToLocalMatrix)).MultiplyPoint3x4(((Component)val3).transform.position);
						val4.transform.localRotation = Quaternion.Inverse(transform.rotation) * ((Component)val3).transform.rotation;
						Vector3 lossyScale2 = ((Component)val3).transform.lossyScale;
						val4.transform.localScale = new Vector3(SafeDiv(lossyScale2.x, lossyScale.x), SafeDiv(lossyScale2.y, lossyScale.y), SafeDiv(lossyScale2.z, lossyScale.z));
						val4.AddComponent<MeshFilter>().sharedMesh = component.sharedMesh;
						MeshRenderer val5 = val4.AddComponent<MeshRenderer>();
						((Renderer)val5).sharedMaterials = CloneDummyMaterials(slot, ((Renderer)val3).sharedMaterials);
						((Renderer)val5).shadowCastingMode = ((Renderer)val3).shadowCastingMode;
						((Renderer)val5).receiveShadows = ((Renderer)val3).receiveShadows;
						extraLit.Add(val5);
						Bounds val6 = TransformBounds(worldToLocalMatrix * ((Component)val3).transform.localToWorldMatrix, component.sharedMesh.bounds);
						if (!flag)
						{
							val2 = val6;
							flag = true;
						}
						else
						{
							((Bounds)(ref val2)).Encapsulate(val6);
						}
						num++;
					}
				}
				if (num == 0)
				{
					Object.Destroy((Object)(object)val);
					Plugin.Activity("Disguise: sitting weapon '" + ((Object)sitting).name + "' had no copyable renderer - bare pedestal.");
					return true;
				}
				dummyT = val.transform;
				Plugin.Activity($"Disguise: weapon dummy '{((Object)sitting).name}' copied ({num} parts).");
			}
			catch (Exception e2)
			{
				Plugin.LogOnce("Disguise.WeaponDummyCopy", e2);
				dummyT = null;
				try
				{
					Object.Destroy((Object)(object)val);
				}
				catch
				{
				}
				return true;
			}
			try
			{
				GameObject val7 = new GameObject("PropHunt_Hitbox");
				val7.layer = 11;
				val7.transform.SetParent(val.transform, false);
				BoxCollider val8 = val7.AddComponent<BoxCollider>();
				((Collider)val8).isTrigger = false;
				val8.center = ((Bounds)(ref val2)).center;
				val8.size = ((Bounds)(ref val2)).size;
				if ((Object)(object)cc != (Object)null)
				{
					Physics.IgnoreCollision((Collider)(object)val8, (Collider)(object)cc, true);
				}
				if (HitboxResolvesHider(val7, hiderPh))
				{
					return true;
				}
				Plugin.Log.LogWarning((object)"Disguise: weapon-dummy hitbox wouldn't resolve the hider - keeping the humanoid hitbox.");
				Object.Destroy((Object)(object)val7);
				return false;
			}
			catch (Exception e3)
			{
				Plugin.LogOnce("Disguise.WeaponHitbox", e3);
				return false;
			}
		}

		private static Material[] CloneDummyMaterials(HiderSlot slot, Material[] src)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			if (src == null)
			{
				return null;
			}
			Material[] array = (Material[])(object)new Material[src.Length];
			for (int i = 0; i < src.Length; i++)
			{
				Material val = src[i];
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				try
				{
					Material val2 = new Material(val);
					slot.OwnedMaterials.Add(val2);
					if (val2.HasProperty("_OutlineWidth"))
					{
						val2.SetFloat("_OutlineWidth", 0f);
					}
					array[i] = val2;
				}
				catch (Exception e)
				{
					Plugin.LogOnce("Disguise.DummyMaterials", e);
					array[i] = val;
				}
			}
			return array;
		}

		private static bool AnyAncestorOnLayer(Transform t, Transform stopAt, int layerA, int layerB)
		{
			Transform val = t;
			while ((Object)(object)val != (Object)null)
			{
				int layer = ((Component)val).gameObject.layer;
				if (layer == layerA || layer == layerB)
				{
					return true;
				}
				if ((Object)(object)val == (Object)(object)stopAt)
				{
					break;
				}
				val = val.parent;
			}
			return false;
		}

		private static void CopySpawnerLights(GameObject clone, Transform spawnerT, Matrix4x4 w2l)
		{
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Expected O, but got Unknown
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			int num = 0;
			try
			{
				Light[] componentsInChildren = ((Component)spawnerT).GetComponentsInChildren<Light>(false);
				foreach (Light val in componentsInChildren)
				{
					if ((Object)(object)val == (Object)null || !((Behaviour)val).enabled)
					{
						continue;
					}
					GameObject game