Decompiled source of TheUncatalogued v0.0.1

plugins/TheUncatalogued.dll

Decompiled 11 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Threading;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using Photon.Voice;
using Photon.Voice.Unity;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.Events;
using UnityEngine.LowLevel;
using UnityEngine.PlayerLoop;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("TheUncatalogued")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.0.1.0")]
[assembly: AssemblyInformationalVersion("0.0.1")]
[assembly: AssemblyProduct("TheUncatalogued")]
[assembly: AssemblyTitle("TheUncatalogued")]
[assembly: AssemblyVersion("0.0.1.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 TheCarousel
{
	internal sealed class AnatomistController : MonoBehaviour, IModEnemyTumbleReceiver
	{
		private enum BehaviourState
		{
			Planting,
			Waiting,
			Attacking,
			Relocating,
			Dead
		}

		private const float AttackWindupSeconds = 0.56f;

		private const float AttackLiftSeconds = 1.08f;

		private const float AttackLiftEndSeconds = 1.6400001f;

		private const float AttackFinishSeconds = 2.04f;

		private readonly List<SpawnedAnatomistPart> _body = new List<SpawnedAnatomistPart>();

		private readonly List<SpawnedAnatomistPart> _heads = new List<SpawnedAnatomistPart>();

		private SpawnedAnatomistPart _cable;

		private SpawnedAnatomistPart _palm;

		private PlayerAvatar _victim;

		private PlayerTumble _victimTumble;

		private PhysGrabObject _victimPhys;

		private Rigidbody _victimBody;

		private BehaviourState _state;

		private Vector3 _floorPoint;

		private Vector3 _ceilingPoint;

		private Vector3 _attackDropPoint;

		private Quaternion _handRotation = Quaternion.identity;

		private float _stateTimer;

		private float _headTimer;

		private float _carrySyncTimer;

		private float _lastClaimedWeaponHitTime = -999f;

		private float _rewardTimer;

		private float _soundTimer;

		private int _health;

		private int _cableCount;

		private bool _headCreatedThisCycle;

		private bool _crushApplied;

		private bool _victimDropped;

		private bool _initialized;

		private bool _cleaning;

		private bool _rewardDropped;

		private bool _firstHeadLogged;

		private bool _firstAttackLogged;

		private bool _firstDescentLogged;

		private bool _relocationEndsWaiting;

		private bool _relocatedDuringTransition;

		private float _postRelocationHeadDelayScale = 1f;

		private static readonly FieldInfo PlayerTumbleField = typeof(PlayerAvatar).GetField("tumble", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		private static readonly FieldInfo GrabbedPhysObjectField = typeof(PhysGrabber).GetField("grabbedPhysGrabObject", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		private static readonly float[] FingerPhase = new float[5] { 0.18f, 1.43f, 2.72f, 4.31f, 5.66f };

		private static readonly float[] FingerCharacter = new float[5] { -0.16f, 0.09f, -0.05f, 0.18f, -0.11f };

		private static readonly float[] FingerCloseDelay = new float[5] { 0.02f, 0.11f, 0.06f, 0.15f, 0.08f };

		public bool CanReceiveTumbleAttack
		{
			get
			{
				if (_initialized)
				{
					return _state != BehaviourState.Dead;
				}
				return false;
			}
		}

		internal bool Initialize(Vector3 position)
		{
			//IL_0006: 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_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: 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_01c6: Unknown result type (might be due to invalid IL or missing references)
			((Component)this).transform.position = position;
			_health = Mathf.Max(1, Plugin.Settings.AnatomistHealth.Value);
			if (!TrySetStation(position))
			{
				return false;
			}
			_cableCount = Mathf.Clamp(Mathf.CeilToInt((_ceilingPoint.y - _floorPoint.y) / 1.05f), 7, 26);
			for (int i = 0; i < _cableCount; i++)
			{
				SpawnedAnatomistPart spawnedAnatomistPart = SpawnBody(AnatomistSpawner.CableResourcePath, new Vector3(0.05f, 0.155f, 0.05f), (AnatomistPartRole)i);
				if (i == 0)
				{
					_cable = spawnedAnatomistPart;
				}
				if (spawnedAnatomistPart == null)
				{
					Cleanup();
					return false;
				}
			}
			_palm = SpawnBody(AnatomistSpawner.PalmResourcePath, new Vector3(0.82f, 0.56f, 0.68f), AnatomistPartRole.Palm);
			if (_palm == null)
			{
				Cleanup();
				return false;
			}
			for (int j = 0; j < 5; j++)
			{
				if (SpawnBody(AnatomistSpawner.FingerResourcePath, new Vector3(0.42f, 0.42f, 0.16f), (AnatomistPartRole)(27 + j)) == null)
				{
					Cleanup();
					return false;
				}
			}
			IgnoreSelfCollisions();
			((Component)this).gameObject.AddComponent<AnatomistHitProxy>().Initialize(this, _body);
			for (int k = 0; k < _body.Count; k++)
			{
				((Component)_body[k].Phys).gameObject.AddComponent<TumbleHitProxy>().Initialize(this, k);
			}
			_state = BehaviourState.Planting;
			_stateTimer = 0f;
			_headTimer = Mathf.Clamp(Plugin.Settings.AnatomistHeadInterval.Value, 4f, 40f) * 0.35f;
			_soundTimer = Random.Range(0.7f, 1.15f);
			_handRotation = ResolveDesiredHandRotation();
			_initialized = true;
			PoseArm(0f, clutch: false);
			Plugin.Log.LogInfo((object)$"The Anatomist assembled a {_cableCount}-segment high-ceiling arm and five syringe fingers with {_health} HP.");
			return true;
		}

		private SpawnedAnatomistPart SpawnBody(string resource, Vector3 scale, AnatomistPartRole role)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			SpawnedAnatomistPart spawnedAnatomistPart = AnatomistSpawner.SpawnBodyPart(resource, _ceilingPoint, scale, role);
			if (spawnedAnatomistPart != null)
			{
				_body.Add(spawnedAnatomistPart);
			}
			return spawnedAnatomistPart;
		}

		private void Update()
		{
			if (!_initialized || !SemiFunc.IsMasterClientOrSingleplayer())
			{
				return;
			}
			if (_state == BehaviourState.Dead)
			{
				UpdateDeath();
				return;
			}
			RemoveDestroyedHeads();
			SyncHeadCompanions();
			if (TryFindHeadHolder(out var heldHead, out var holder) && StartAttack(holder))
			{
				AnatomistSpawner.Destroy(heldHead);
				_heads.Remove(heldHead);
			}
			switch (_state)
			{
			case BehaviourState.Attacking:
				UpdateAttack();
				break;
			case BehaviourState.Relocating:
				UpdateRelocating();
				break;
			case BehaviourState.Waiting:
				PoseArm(0f, clutch: false);
				break;
			default:
				UpdatePlanting();
				break;
			}
			UpdateSound();
		}

		private void UpdatePlanting()
		{
			_headTimer -= Time.deltaTime;
			if (_headTimer > 0f)
			{
				PoseArm(0f, clutch: false);
				return;
			}
			_stateTimer += Time.deltaTime;
			float num = ((_stateTimer < 1.5f) ? Mathf.SmoothStep(0f, 1f, _stateTimer / 1.5f) : ((!(_stateTimer < 2.05f)) ? (1f - Mathf.SmoothStep(0f, 1f, Mathf.Clamp01((_stateTimer - 2.05f) / 1.4f))) : 1f));
			PoseArm(num, clutch: false);
			if (!_firstDescentLogged && num >= 0.35f)
			{
				_firstDescentLogged = true;
				Plugin.Log.LogInfo((object)"The Anatomist began its first visibly interpolated ceiling-to-floor descent.");
			}
			if (!_headCreatedThisCycle && _stateTimer >= 1.76f)
			{
				_headCreatedThisCycle = true;
				SpawnHead();
			}
			if (!(_stateTimer < 3.45f))
			{
				_stateTimer = 0f;
				_headCreatedThisCycle = false;
				int num2 = Mathf.Clamp(Plugin.Settings.AnatomistMaximumHeads.Value, 1, 6);
				if (_heads.Count >= num2)
				{
					BeginRelocation(endsWaiting: true, 1f);
				}
				else
				{
					BeginRelocation(endsWaiting: false, 1f);
				}
			}
		}

		private void SpawnHead()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			SpawnedAnatomistPart spawnedAnatomistPart = AnatomistSpawner.SpawnDummyHead(_floorPoint + Vector3.up * 0.035f);
			if (spawnedAnatomistPart != null)
			{
				_heads.Add(spawnedAnatomistPart);
				if (!_firstHeadLogged)
				{
					_firstHeadLogged = true;
					Plugin.Log.LogInfo((object)"The Anatomist dropped its first grabbable networked dummy head.");
				}
			}
		}

		private bool TryFindHeadHolder(out SpawnedAnatomistPart heldHead, out PlayerAvatar holder)
		{
			heldHead = null;
			holder = null;
			foreach (SpawnedAnatomistPart head in _heads)
			{
				if ((Object)(object)head?.Phys == (Object)null || !head.Alive)
				{
					continue;
				}
				foreach (PhysGrabber item in head.Phys.playerGrabbing)
				{
					if ((Object)(object)item?.playerAvatar != (Object)null && GunAccess.IsLiving(item.playerAvatar))
					{
						heldHead = head;
						holder = item.playerAvatar;
						return true;
					}
				}
			}
			if (Time.frameCount % 4 != 0 || GrabbedPhysObjectField == null)
			{
				return false;
			}
			PhysGrabber[] array = Object.FindObjectsOfType<PhysGrabber>();
			foreach (PhysGrabber val in array)
			{
				if ((Object)(object)val?.playerAvatar == (Object)null || !GunAccess.IsLiving(val.playerAvatar))
				{
					continue;
				}
				object? value = GrabbedPhysObjectField.GetValue(val);
				PhysGrabObject val2 = (PhysGrabObject)((value is PhysGrabObject) ? value : null);
				if ((Object)(object)val2 == (Object)null)
				{
					continue;
				}
				foreach (SpawnedAnatomistPart head2 in _heads)
				{
					if (!((Object)(object)head2?.Phys == (Object)null) && head2.Alive && ((Object)(object)val2 == (Object)(object)head2.Phys || ((Component)val2).transform.IsChildOf(head2.Root.transform) || ((Component)head2.Phys).transform.IsChildOf(((Component)val2).transform)))
					{
						heldHead = head2;
						holder = val.playerAvatar;
						ManualLogSource log = Plugin.Log;
						PhotonView photonView = holder.photonView;
						log.LogInfo((object)$"The Anatomist detected a dummy-head grab through the vanilla grabber link for player view {((photonView != null) ? photonView.ViewID : (-1))}.");
						return true;
					}
				}
			}
			return false;
		}

		private bool StartAttack(PlayerAvatar holder)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: 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)
			if (!GunAccess.IsLiving(holder))
			{
				return false;
			}
			Vector3 position = ((Component)holder).transform.position;
			if (!TrySetStation(position))
			{
				return false;
			}
			_victim = holder;
			ref PlayerTumble victimTumble = ref _victimTumble;
			object? obj = PlayerTumbleField?.GetValue(holder);
			victimTumble = (PlayerTumble)((obj is PlayerTumble) ? obj : null);
			if ((Object)(object)_victimTumble == (Object)null)
			{
				_victimTumble = ((IEnumerable<PlayerTumble>)Object.FindObjectsOfType<PlayerTumble>()).FirstOrDefault((Func<PlayerTumble, bool>)((PlayerTumble tumble) => (Object)(object)tumble != (Object)null && (Object)(object)tumble.playerAvatar == (Object)(object)holder));
			}
			_victimPhys = (((Object)(object)_victimTumble != (Object)null) ? ((Component)_victimTumble).GetComponent<PhysGrabObject>() : null);
			object obj2 = _victimPhys?.rb;
			if (obj2 == null)
			{
				PlayerTumble victimTumble2 = _victimTumble;
				obj2 = ((victimTumble2 != null) ? ((Component)victimTumble2).GetComponent<Rigidbody>() : null);
			}
			_victimBody = (Rigidbody)obj2;
			_state = BehaviourState.Attacking;
			_stateTimer = 0f;
			_carrySyncTimer = 0f;
			_crushApplied = false;
			_victimDropped = false;
			PlayerTumble victimTumble3 = _victimTumble;
			if (victimTumble3 != null)
			{
				victimTumble3.TumbleSet(true, false);
			}
			PlayerTumble victimTumble4 = _victimTumble;
			if (victimTumble4 != null)
			{
				victimTumble4.TumbleOverrideTime(2.4f);
			}
			TryFindDropPoint(((Component)holder).transform.position, out _attackDropPoint);
			return true;
		}

		private void UpdateAttack()
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ce: 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_02dd: 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_02f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0301: Unknown result type (might be due to invalid IL or missing references)
			//IL_030b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0310: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0205: 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_0231: Unknown result type (might be due to invalid IL or missing references)
			//IL_0246: Unknown result type (might be due to invalid IL or missing references)
			//IL_028e: 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_00ec: Unknown result type (might be due to invalid IL or missing references)
			if (!GunAccess.IsLiving(_victim))
			{
				FinishAttack();
				return;
			}
			_stateTimer += Time.deltaTime;
			if (_stateTimer < 0.56f)
			{
				float extension = Mathf.SmoothStep(0f, 1f, _stateTimer / 0.56f);
				_floorPoint = ((Component)_victim).transform.position;
				PoseArm(extension, clutch: true);
				return;
			}
			if (!_crushApplied)
			{
				_crushApplied = true;
				PlayerHealth playerHealth = _victim.playerHealth;
				if (playerHealth != null)
				{
					playerHealth.HurtOther(Mathf.Max(1, Plugin.Settings.AnatomistCrushDamage.Value), ((Component)_victim).transform.position, false, -1, false);
				}
				PlayerTumble victimTumble = _victimTumble;
				if (victimTumble != null)
				{
					victimTumble.TumbleSet(true, false);
				}
				EmitImpact("ImpactHeavyRPC", 100f, ((Component)_victim).transform.position);
				if (!_firstAttackLogged)
				{
					_firstAttackLogged = true;
					Plugin.Log.LogInfo((object)$"The Anatomist crushed and abducted its first dummy-head holder for {Plugin.Settings.AnatomistCrushDamage.Value} damage.");
				}
			}
			if (_stateTimer < 1.6400001f)
			{
				float num = Mathf.SmoothStep(0f, 1f, (_stateTimer - 0.56f) / 1.08f);
				PoseArm(1f - num * 0.88f, clutch: true);
				Vector3 val = Vector3.Lerp(((Component)_victim).transform.position, _ceilingPoint - Vector3.up * 0.92f, Mathf.Clamp01(num + 0.16f));
				if ((Object)(object)_victimBody != (Object)null && !_victimBody.isKinematic)
				{
					Vector3 val2 = (val - _victimBody.position) * 12f;
					_victimBody.velocity = Vector3.Lerp(_victimBody.velocity, Vector3.ClampMagnitude(val2, 18f), 1f - Mathf.Exp(-15f * Time.deltaTime));
					Rigidbody victimBody = _victimBody;
					victimBody.angularVelocity *= Mathf.Exp(-10f * Time.deltaTime);
				}
				_carrySyncTimer -= Time.deltaTime;
				if (_carrySyncTimer <= 0f && (Object)(object)_victimPhys != (Object)null)
				{
					_carrySyncTimer = 0.2f;
					_victimPhys.Teleport(val, ((Component)_victim).transform.rotation);
				}
				return;
			}
			if (!_victimDropped)
			{
				_victimDropped = true;
				if ((Object)(object)_victimPhys != (Object)null)
				{
					_victimPhys.Teleport(_attackDropPoint + Vector3.up * 0.7f, Quaternion.identity);
					_victimTumble.TumbleForce(Vector3.down * 2.5f + Random.insideUnitSphere * 1.2f);
				}
			}
			PoseArm(0f, clutch: true);
			if (_stateTimer >= 2.04f)
			{
				FinishAttack();
			}
		}

		private void FinishAttack()
		{
			_victim = null;
			_victimTumble = null;
			_victimPhys = null;
			_victimBody = null;
			_stateTimer = 0f;
			_headCreatedThisCycle = false;
			BeginRelocation(endsWaiting: false, 0.55f);
		}

		private void BeginRelocation(bool endsWaiting, float nextHeadDelayScale)
		{
			_state = BehaviourState.Relocating;
			_stateTimer = 0f;
			_relocationEndsWaiting = endsWaiting;
			_relocatedDuringTransition = false;
			_postRelocationHeadDelayScale = Mathf.Max(0.05f, nextHeadDelayScale);
		}

		private void UpdateRelocating()
		{
			_stateTimer += Time.deltaTime;
			if (_stateTimer < 0.72f)
			{
				float ceilingHide = Mathf.SmoothStep(0f, 1f, _stateTimer / 0.72f);
				PoseArm(0f, clutch: false, ceilingHide);
				return;
			}
			PoseArm(0f, clutch: false, 1f);
			if (!_relocatedDuringTransition && _stateTimer >= 0.94f)
			{
				TryRelocate(_relocationEndsWaiting);
				_relocatedDuringTransition = true;
			}
			if (_stateTimer < 1.16f)
			{
				return;
			}
			float num = Mathf.SmoothStep(0f, 1f, Mathf.Clamp01((_stateTimer - 1.16f) / 0.72f));
			PoseArm(0f, clutch: false, 1f - num);
			if (!(_stateTimer < 1.88f))
			{
				_stateTimer = 0f;
				_state = (_relocationEndsWaiting ? BehaviourState.Waiting : BehaviourState.Planting);
				if (!_relocationEndsWaiting)
				{
					_headTimer = Mathf.Clamp(Plugin.Settings.AnatomistHeadInterval.Value, 4f, 40f) * _postRelocationHeadDelayScale;
				}
				PoseArm(0f, clutch: false);
			}
		}

		private void PoseArm(float extension, bool clutch, float ceilingHide = 0f)
		{
			//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_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_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: 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_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: 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_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: 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_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: 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_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_0324: Unknown result type (might be due to invalid IL or missing references)
			//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_032d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0332: Unknown result type (might be due to invalid IL or missing references)
			//IL_035f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0363: Unknown result type (might be due to invalid IL or missing references)
			//IL_0368: Unknown result type (might be due to invalid IL or missing references)
			//IL_036d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0371: Unknown result type (might be due to invalid IL or missing references)
			//IL_0376: Unknown result type (might be due to invalid IL or missing references)
			//IL_0378: Unknown result type (might be due to invalid IL or missing references)
			//IL_0379: Unknown result type (might be due to invalid IL or missing references)
			//IL_0382: Unknown result type (might be due to invalid IL or missing references)
			//IL_0387: Unknown result type (might be due to invalid IL or missing references)
			//IL_038c: Unknown result type (might be due to invalid IL or missing references)
			//IL_039c: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b2: 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_0436: Unknown result type (might be due to invalid IL or missing references)
			//IL_0438: Unknown result type (might be due to invalid IL or missing references)
			//IL_043c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0441: Unknown result type (might be due to invalid IL or missing references)
			//IL_0446: 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_0455: Unknown result type (might be due to invalid IL or missing references)
			//IL_0457: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d1: 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_03d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_03df: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0404: Unknown result type (might be due to invalid IL or missing references)
			extension = Mathf.Clamp01(extension);
			ceilingHide = Mathf.Clamp01(ceilingHide);
			Vector3 val = Vector3.Lerp(_ceilingPoint - Vector3.up * 0.22f + Vector3.up * (1.1f * ceilingHide), _floorPoint + Vector3.up * (clutch ? 1.25f : 0.92f), extension) - Vector3.up * 0.1f;
			Quaternion val2 = ResolveDesiredHandRotation();
			float num = 1f - Mathf.Exp((0f - Mathf.Max(0.001f, Time.deltaTime)) * 5.5f);
			_handRotation = Quaternion.Slerp(_handRotation, val2, num);
			Vector3 val3 = _handRotation * Vector3.right;
			Vector3 val4 = _handRotation * Vector3.up;
			Vector3 val5 = _handRotation * Vector3.forward;
			Vector3 visualCenter = val - val4 * 0.045f;
			Vector3 val6 = val + Vector3.up * 0.015f;
			Vector3 val9;
			for (int i = 0; i < _cableCount; i++)
			{
				float num2 = (float)i / (float)_cableCount;
				float num3 = ((float)i + 1f) / (float)_cableCount;
				Vector3 val7 = Vector3.Lerp(_ceilingPoint, val6, num2);
				Vector3 val8 = Vector3.Lerp(_ceilingPoint, val6, num3);
				val9 = val8 - val7;
				Vector3 val10 = ((Vector3)(ref val9)).normalized * 0.035f;
				PoseSegment(FindRole((AnatomistPartRole)i), (i == 0) ? val7 : (val7 - val10), (i == _cableCount - 1) ? val8 : (val8 + val10));
			}
			PosePoint(_palm, visualCenter, _handRotation);
			for (int j = 0; j < 5; j++)
			{
				float num4 = ((float)j - 2f) / 2f;
				float num5 = FingerCharacter[j];
				float num6 = Mathf.Clamp01((extension - FingerCloseDelay[j]) / Mathf.Max(0.05f, 1f - FingerCloseDelay[j]));
				float num7 = (clutch ? Mathf.SmoothStep(0f, 1f, num6) : Mathf.SmoothStep(0f, 1f, Mathf.InverseLerp(0.44f, 1f, num6)));
				num7 *= 0.9f + num5 * 0.22f;
				float num8 = Mathf.Sin(Time.time * ((clutch ? 4f : 2.35f) + (float)j * 0.17f) + FingerPhase[j]);
				float num9 = Mathf.Sin(Time.time * (1.35f + (float)j * 0.11f) + FingerPhase[j] * 1.73f);
				float num10 = Mathf.Lerp(24f + num5 * 5f, 13f + num5 * 4f, num7);
				Vector3 val11 = Quaternion.AngleAxis(num4 * num10 + num8 * Mathf.Lerp(10.5f, 3.8f, num7) + num9 * 3f, val5) * -val4;
				float num11 = Mathf.Lerp(num5 * 0.008f, 0.06f + num5 * 0.018f, num7) + num8 * 0.008f;
				val9 = val11 + val5 * num11;
				Vector3 normalized = ((Vector3)(ref val9)).normalized;
				Vector3 val12 = val + val3 * (num4 * 0.055f) - val4 * (0.034f - num5 * 0.006f) + val5 * 0.01f;
				if (clutch)
				{
					Vector3 val13 = _floorPoint + Vector3.up * 0.88f - val12;
					val9 = Vector3.Slerp(normalized, ((Vector3)(ref val13)).normalized, 0.66f + num7 * 0.2f);
					normalized = ((Vector3)(ref val9)).normalized;
				}
				float num12 = Mathf.Lerp(0.5f, 0.43f, Mathf.Abs(num4)) * (1f + num5 * 0.11f + num9 * 0.045f);
				Vector3 end = val12 + normalized * num12;
				PoseSegment(FindRole((AnatomistPartRole)(27 + j)), val12, end, val5);
			}
		}

		private Quaternion ResolveDesiredHandRotation()
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: 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_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			PlayerAvatar val = null;
			float num = float.MaxValue;
			foreach (PlayerAvatar item in SemiFunc.PlayerGetList())
			{
				if (GunAccess.IsLiving(item))
				{
					Vector3 val2 = ((Component)item).transform.position - _floorPoint;
					val2.y = 0f;
					float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude;
					if (sqrMagnitude < num)
					{
						num = sqrMagnitude;
						val = item;
					}
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				return _handRotation;
			}
			Vector3 val3 = ((Component)val).transform.position - _floorPoint;
			val3.y = 0f;
			if (!(((Vector3)(ref val3)).sqrMagnitude > 0.001f))
			{
				return _handRotation;
			}
			return Quaternion.LookRotation(((Vector3)(ref val3)).normalized, Vector3.up);
		}

		private SpawnedAnatomistPart FindRole(AnatomistPartRole role)
		{
			return _body.FirstOrDefault((SpawnedAnatomistPart part) => part.Role == role);
		}

		private static void PoseSegment(SpawnedAnatomistPart part, Vector3 start, Vector3 end, Vector3? preferredFacing = null)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: 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_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)part?.Phys == (Object)null))
			{
				Vector3 val = end - start;
				if (((Vector3)(ref val)).sqrMagnitude < 0.0001f)
				{
					val = Vector3.down * 0.01f;
				}
				Vector3 normalized = ((Vector3)(ref val)).normalized;
				Quaternion rotation = StableSegmentRotation(part, normalized, (Vector3)(((??)preferredFacing) ?? Vector3.forward));
				PosePoint(part, (start + end) * 0.5f, rotation);
			}
		}

		private static Quaternion StableSegmentRotation(SpawnedAnatomistPart part, Vector3 direction, Vector3 preferredFacing)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			Quaternion val = Quaternion.FromToRotation(part.LongAxisLocal, direction);
			Vector3 val2 = ((Mathf.Abs(Vector3.Dot(((Vector3)(ref part.LongAxisLocal)).normalized, Vector3.forward)) < 0.92f) ? Vector3.forward : Vector3.right);
			Vector3 val3 = Vector3.ProjectOnPlane(val * val2, direction);
			Vector3 val4 = Vector3.ProjectOnPlane(preferredFacing, direction);
			if (((Vector3)(ref val4)).sqrMagnitude < 0.0001f)
			{
				val4 = Vector3.ProjectOnPlane(Vector3.right, direction);
			}
			if (((Vector3)(ref val3)).sqrMagnitude < 0.0001f || ((Vector3)(ref val4)).sqrMagnitude < 0.0001f)
			{
				return val;
			}
			return Quaternion.AngleAxis(Vector3.SignedAngle(((Vector3)(ref val3)).normalized, ((Vector3)(ref val4)).normalized, direction), direction) * val;
		}

		private static void PosePoint(SpawnedAnatomistPart part, Vector3 visualCenter, Quaternion rotation)
		{
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: 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: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: 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_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//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_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: 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_0093: 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_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: 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_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_0217: Unknown result type (might be due to invalid IL or missing references)
			//IL_023e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)part?.Phys == (Object)null)
			{
				return;
			}
			if (part.GeometryCalibrationFrames > 0)
			{
				AnatomistSpawner.RefreshGeometry(part, refreshLongAxis: false);
				part.GeometryCalibrationFrames--;
				if (part.GeometryCalibrationFrames == 0 && !part.GeometryLogged)
				{
					part.GeometryLogged = true;
					Plugin.Log.LogInfo((object)$"Anatomist geometry {part.Role}: resource={part.ResourcePath}, rendered={part.VisualSize}, centerOffset={part.VisualCenterOffset}, axis={part.LongAxisLocal}.");
				}
			}
			part.ImpactDetector.destroyDisable = true;
			part.Phys.OverrideIndestructible(0.3f);
			part.Phys.OverrideGrabDisable(0.3f);
			part.Phys.OverrideKinematic(0.3f);
			if (!part.PoseInitialized)
			{
				part.SmoothedVisualCenter = visualCenter;
				part.SmoothedRotation = rotation;
				part.PoseInitialized = true;
			}
			else
			{
				float num = 1f - Mathf.Exp(-9f * Time.deltaTime);
				float num2 = 1f - Mathf.Exp(-7f * Time.deltaTime);
				part.SmoothedVisualCenter = Vector3.Lerp(part.SmoothedVisualCenter, visualCenter, num);
				part.SmoothedRotation = Quaternion.Slerp(part.SmoothedRotation, rotation, num2);
			}
			Vector3 val = part.SmoothedVisualCenter - part.SmoothedRotation * part.VisualCenterOffset;
			Vector3 val2 = ((Component)part.Phys).transform.position - val;
			if (!(((Vector3)(ref val2)).sqrMagnitude > 1E-06f) && !(Quaternion.Angle(((Component)part.Phys).transform.rotation, part.SmoothedRotation) > 0.05f))
			{
				return;
			}
			part.Phys.SetPositionLogic(val, part.SmoothedRotation);
			((Component)part.Phys).transform.SetPositionAndRotation(val, part.SmoothedRotation);
			if ((Object)(object)part.Phys.rb != (Object)null)
			{
				part.Phys.rb.position = val;
				part.Phys.rb.rotation = part.SmoothedRotation;
				if (!part.Phys.rb.isKinematic)
				{
					part.Phys.rb.velocity = Vector3.zero;
					part.Phys.rb.angularVelocity = Vector3.zero;
				}
			}
		}

		private void SyncHeadCompanions()
		{
			//IL_0142: 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)
			foreach (SpawnedAnatomistPart head in _heads)
			{
				if ((Object)(object)head?.Phys == (Object)null || !head.Alive)
				{
					continue;
				}
				head.ImpactDetector.destroyDisable = true;
				head.Phys.OverrideIndestructible(0.4f);
				UpdateHeadDiscovery(head);
				if (head.HeadActivationRepeats <= 0)
				{
					continue;
				}
				head.HeadActivationTimer -= Time.deltaTime;
				if (head.HeadActivationTimer > 0f)
				{
					continue;
				}
				head.HeadActivationTimer = 0.5f;
				head.HeadActivationRepeats--;
				Collider[] array = head.Colliders ?? Array.Empty<Collider>();
				foreach (Collider val in array)
				{
					if ((Object)(object)val != (Object)null)
					{
						val.enabled = true;
					}
				}
				if (!head.HeadActivated)
				{
					head.HeadActivated = true;
					head.Phys.clientNonKinematic = true;
					if ((Object)(object)head.Phys.rb != (Object)null)
					{
						head.Phys.rb.isKinematic = false;
						head.Phys.rb.collisionDetectionMode = (CollisionDetectionMode)2;
						head.Phys.rb.interpolation = (RigidbodyInterpolation)1;
					}
					head.Phys.Teleport(head.HeadSpawnPosition, head.HeadSpawnRotation);
				}
				if (GameManager.Multiplayer() && (Object)(object)head.View != (Object)null)
				{
					head.View.RPC("OverrideSpectatedRPC", (RpcTarget)1, new object[1] { false });
					if (!head.HeadColorSent)
					{
						head.HeadColorSent = true;
						head.View.RPC("SetupColorsAllRPC", (RpcTarget)4, new object[1] { head.HeadColorIndex });
					}
				}
			}
		}

		private void UpdateHeadDiscovery(SpawnedAnatomistPart head)
		{
			if ((Object)(object)head?.DeathHead == (Object)null || (Object)(object)head.Phys == (Object)null)
			{
				return;
			}
			if (!head.HeadDiscovered)
			{
				MapCustom mapCustom = head.DeathHead.mapCustom;
				if (mapCustom != null)
				{
					mapCustom.Hide();
				}
			}
			bool flag = IsHeadSeenByLocalPlayer(head);
			if (!head.HeadDiscovered && (flag || IsHeadSeenByRemotePlayer(head)))
			{
				head.HeadDiscovered = true;
				if (GameManager.Multiplayer() && (Object)(object)head.View != (Object)null)
				{
					head.View.RPC("SeenSetRPC", (RpcTarget)3, new object[1] { true });
				}
				else
				{
					Traverse.Create((object)head.DeathHead).Field("serverSeen").SetValue((object)true);
				}
				Plugin.Log.LogInfo((object)"The Anatomist's first dummy head was identified and published as a vanilla red death-head map marker.");
			}
			if (flag && !head.HeadHostDiscoverGraphicShown && (Object)(object)ValuableDiscover.instance != (Object)null)
			{
				head.HeadHostDiscoverGraphicShown = true;
				ValuableDiscover.instance.New(head.Phys, (State)2, (ValuableDiscoverCustom)null);
			}
		}

		private static bool IsHeadSeenByLocalPlayer(SpawnedAnatomistPart head)
		{
			//IL_0059: 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)
			if ((Object)(object)PlayerController.instance == (Object)null || (Object)(object)PlayerController.instance.playerAvatarScript == (Object)null || !GunAccess.IsLiving(PlayerController.instance.playerAvatarScript))
			{
				return false;
			}
			PlayerLocalCamera localCamera = PlayerController.instance.playerAvatarScript.localCamera;
			Transform val = ((localCamera != null) ? localCamera.GetOverrideTransform() : null);
			if ((Object)(object)val != (Object)null)
			{
				return IsHeadVisibleFrom(head, val.position, val.forward, requireLocalOnScreen: true);
			}
			return false;
		}

		private static bool IsHeadSeenByRemotePlayer(SpawnedAnatomistPart head)
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			if (!GameManager.Multiplayer() || (Object)(object)GameDirector.instance == (Object)null)
			{
				return false;
			}
			foreach (PlayerAvatar player in GameDirector.instance.PlayerList)
			{
				if (!((Object)(object)player == (Object)null) && !((Object)(object)player == (Object)(object)PlayerController.instance?.playerAvatarScript) && GunAccess.IsLiving(player))
				{
					Vector3 eye = ((Component)player).transform.position + Vector3.up * 1.35f;
					if (IsHeadVisibleFrom(head, eye, ((Component)player).transform.forward, requireLocalOnScreen: false))
					{
						return true;
					}
				}
			}
			return false;
		}

		private static bool IsHeadVisibleFrom(SpawnedAnatomistPart head, Vector3 eye, Vector3 forward, bool requireLocalOnScreen)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			Vector3 centerPoint = head.Phys.centerPoint;
			Vector3 val = centerPoint - eye;
			float magnitude = ((Vector3)(ref val)).magnitude;
			if (magnitude > 10f || magnitude < 0.05f)
			{
				return false;
			}
			Vector3 val2 = val / magnitude;
			if (Vector3.Dot(((Vector3)(ref forward)).normalized, val2) < 0.63f)
			{
				return false;
			}
			if (requireLocalOnScreen && !SemiFunc.OnScreen(centerPoint, -0.15f, -0.15f))
			{
				return false;
			}
			return !Physics.Raycast(eye, val2, magnitude, LayerMask.GetMask(new string[1] { "Default" }), (QueryTriggerInteraction)1);
		}

		private void UpdateSound()
		{
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			_soundTimer -= Time.deltaTime;
			if (!(_soundTimer > 0f) && !((Object)(object)_palm?.ImpactDetector == (Object)null) && !((Object)(object)_palm.Phys == (Object)null))
			{
				_soundTimer = Random.Range(0.75f, 1.25f);
				_palm.ImpactDetector.ImpactLight(82f, _palm.Phys.centerPoint);
			}
		}

		private bool TrySetStation(Vector3 candidate)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			NavMeshHit val = default(NavMeshHit);
			if (!NavMesh.SamplePosition(candidate, ref val, 6f, -1))
			{
				return false;
			}
			if (!TryFindRealCeiling(((NavMeshHit)(ref val)).position, out var ceiling))
			{
				return false;
			}
			SetStation(((NavMeshHit)(ref val)).position, ceiling);
			return true;
		}

		private static bool TryFindRealCeiling(Vector3 floor, out Vector3 ceiling)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			foreach (RaycastHit item in from candidate in Physics.RaycastAll(floor + Vector3.up * 0.25f, Vector3.up, 28.5f, LayerMask.op_Implicit(SemiFunc.LayerMaskGetVisionObstruct()), (QueryTriggerInteraction)1)
				orderby ((RaycastHit)(ref candidate)).distance descending
				select candidate)
			{
				RaycastHit current = item;
				float num = ((RaycastHit)(ref current)).point.y - floor.y;
				if (!(num < 1.65f) && !(num > 28f) && !(((RaycastHit)(ref current)).normal.y > -0.2f))
				{
					ceiling = ((RaycastHit)(ref current)).point - Vector3.up * 0.1f;
					return true;
				}
			}
			ceiling = Vector3.zero;
			return false;
		}

		private void SetStation(Vector3 floor, Vector3 ceiling)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			_floorPoint = floor;
			_ceilingPoint = ceiling;
			((Component)this).transform.position = floor;
			foreach (SpawnedAnatomistPart item in _body)
			{
				if (item != null)
				{
					item.PoseInitialized = false;
				}
			}
		}

		private bool TryRelocate(bool hidden)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: 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_003b: Unknown result type (might be due to invalid IL or missing references)
			Vector3 floorPoint = _floorPoint;
			LevelPoint val = (hidden ? SemiFunc.LevelPointGetFurthestFromPlayer(floorPoint, 8f) : SemiFunc.LevelPointGetPlayerDistance(floorPoint, 10f, 55f, false));
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			return TrySetStation(((Component)val).transform.position);
		}

		private static bool TryFindDropPoint(Vector3 origin, out Vector3 point)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			LevelPoint val = SemiFunc.LevelPointGetPlayerDistance(origin, 10f, 45f, false) ?? SemiFunc.LevelPointGetFurthestFromPlayer(origin, 6f);
			Vector3 val2 = (((Object)(object)val != (Object)null) ? ((Component)val).transform.position : (origin + Random.onUnitSphere * 10f));
			val2.y = origin.y;
			NavMeshHit val3 = default(NavMeshHit);
			if (NavMesh.SamplePosition(val2, ref val3, 7f, -1))
			{
				point = ((NavMeshHit)(ref val3)).position;
				return true;
			}
			point = origin;
			return false;
		}

		private void IgnoreSelfCollisions()
		{
			for (int i = 0; i < _body.Count; i++)
			{
				for (int j = i + 1; j < _body.Count; j++)
				{
					Collider[] array = _body[i].Colliders ?? Array.Empty<Collider>();
					foreach (Collider val in array)
					{
						Collider[] array2 = _body[j].Colliders ?? Array.Empty<Collider>();
						foreach (Collider val2 in array2)
						{
							if ((Object)(object)val != (Object)null && (Object)(object)val2 != (Object)null)
							{
								Physics.IgnoreCollision(val, val2, true);
							}
						}
					}
				}
			}
		}

		private void RemoveDestroyedHeads()
		{
			for (int num = _heads.Count - 1; num >= 0; num--)
			{
				SpawnedAnatomistPart spawnedAnatomistPart = _heads[num];
				if (spawnedAnatomistPart == null || !spawnedAnatomistPart.Alive || (Object)(object)spawnedAnatomistPart.Root == (Object)null || (Object)(object)spawnedAnatomistPart.Phys == (Object)null || spawnedAnatomistPart.Phys.dead)
				{
					_heads.RemoveAt(num);
				}
			}
			if (_state == BehaviourState.Waiting && _heads.Count < Mathf.Clamp(Plugin.Settings.AnatomistMaximumHeads.Value, 1, 6))
			{
				BeginRelocation(endsWaiting: false, 0.5f);
			}
		}

		internal bool TryClaimWeaponHit(int sourceId)
		{
			if (_state == BehaviourState.Dead || !ModEnemyWeaponDamage.TryClaim((Object)(object)this, sourceId) || Time.time - _lastClaimedWeaponHitTime < 0.06f)
			{
				return false;
			}
			_lastClaimedWeaponHitTime = Time.time;
			return true;
		}

		internal void ReceiveWeaponHit(Vector3 hitPosition, int damage)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			if (_state != BehaviourState.Dead && damage > 0)
			{
				damage = ParasiteEffectRegistry.ModifyEnemyDamageAt(hitPosition, damage);
				_health -= damage;
				ModEnemyFeedback.DamageHit(_palm?.ImpactDetector, _palm?.Phys, hitPosition, 90f);
				if (_health <= 0)
				{
					Die();
				}
			}
		}

		public void ReceiveTumbleAttack(int partIndex, int damage, Vector3 hitPosition, Vector3 direction)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			ReceiveWeaponHit(hitPosition, Mathf.Max(1, damage));
		}

		internal void ExecuteForLab()
		{
			if (_state != BehaviourState.Dead)
			{
				_health = 0;
				Die();
			}
		}

		private void Die()
		{
			if (_state == BehaviourState.Dead)
			{
				return;
			}
			_state = BehaviourState.Dead;
			foreach (SpawnedAnatomistPart item in _body)
			{
				if (item.Alive)
				{
					item.Alive = false;
					item.ImpactDetector.destroyDisable = false;
					item.ImpactDetector.DestroyObject(true);
				}
			}
			foreach (SpawnedAnatomistPart item2 in _heads.ToList())
			{
				AnatomistSpawner.Destroy(item2);
			}
			_heads.Clear();
			_rewardTimer = 0.08f;
		}

		private void UpdateDeath()
		{
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			if (_rewardDropped)
			{
				return;
			}
			_rewardTimer -= Time.deltaTime;
			if (_rewardTimer > 0f)
			{
				return;
			}
			_rewardDropped = true;
			if (!Plugin.Settings.AnatomistDropEnemyValuable.Value || (Object)(object)AssetManager.instance == (Object)null)
			{
				return;
			}
			GameObject val = (GameObject)(Mathf.Clamp(Plugin.Settings.AnatomistRewardTier.Value, 1, 3) switch
			{
				2 => AssetManager.instance.enemyValuableMedium, 
				1 => AssetManager.instance.enemyValuableSmall, 
				_ => AssetManager.instance.enemyValuableBig, 
			});
			if (!((Object)(object)val == (Object)null))
			{
				if (GameManager.Multiplayer())
				{
					PhotonNetwork.InstantiateRoomObject("Valuables/" + ((Object)val).name, ((Component)this).transform.position + Vector3.up * 0.45f, Quaternion.identity, (byte)0, (object[])null);
				}
				else
				{
					Object.Instantiate<GameObject>(val, ((Component)this).transform.position + Vector3.up * 0.45f, Quaternion.identity);
				}
			}
		}

		private void EmitImpact(string rpcName, float force, Vector3 position)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			PhotonView val = _palm?.View;
			if ((Object)(object)val != (Object)null && GameManager.Multiplayer())
			{
				val.RPC(rpcName, (RpcTarget)0, new object[2] { force, position });
			}
			else if ((Object)(object)_palm?.ImpactDetector != (Object)null)
			{
				_palm.ImpactDetector.ImpactHeavy(force, position);
			}
		}

		private void OnDestroy()
		{
			if (_initialized && !_cleaning && SemiFunc.IsMasterClientOrSingleplayer())
			{
				Cleanup();
			}
		}

		private void Cleanup()
		{
			if (_cleaning)
			{
				return;
			}
			_cleaning = true;
			foreach (SpawnedAnatomistPart item in _body)
			{
				if (item.Alive)
				{
					AnatomistSpawner.Destroy(item);
				}
			}
			foreach (SpawnedAnatomistPart head in _heads)
			{
				if (head.Alive)
				{
					AnatomistSpawner.Destroy(head);
				}
			}
		}
	}
	internal sealed class AnatomistHitProxy : MonoBehaviour
	{
		private AnatomistController _controller;

		private Renderer[] _renderers = Array.Empty<Renderer>();

		private PhysGrabObjectImpactDetector[] _detectors = Array.Empty<PhysGrabObjectImpactDetector>();

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

		private readonly HashSet<int> _current = new HashSet<int>();

		private float _cooldown;

		private static int _bulletFrame = -1;

		private static ItemGunBullet[] _bullets = Array.Empty<ItemGunBullet>();

		internal void Initialize(AnatomistController controller, IEnumerable<SpawnedAnatomistPart> parts)
		{
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Expected O, but got Unknown
			_controller = controller;
			List<Renderer> list = new List<Renderer>();
			List<PhysGrabObjectImpactDetector> list2 = new List<PhysGrabObjectImpactDetector>();
			foreach (SpawnedAnatomistPart part in parts)
			{
				if (part?.Renderers != null)
				{
					list.AddRange(part.Renderers);
				}
				if ((Object)(object)part?.ImpactDetector != (Object)null)
				{
					list2.Add(part.ImpactDetector);
					UnityEvent onHurtColliderHit = part.ImpactDetector.onHurtColliderHit;
					if (onHurtColliderHit != null)
					{
						onHurtColliderHit.AddListener(new UnityAction(OnHurtColliderHit));
					}
				}
			}
			_renderers = list.ToArray();
			_detectors = list2.ToArray();
		}

		private void Update()
		{
			_cooldown = Mathf.Max(0f, _cooldown - Time.deltaTime);
			if (_cooldown <= 0f && SemiFunc.IsMasterClientOrSingleplayer())
			{
				DetectExpandedBulletHit();
			}
		}

		private void OnDestroy()
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			PhysGrabObjectImpactDetector[] detectors = _detectors;
			foreach (PhysGrabObjectImpactDetector obj in detectors)
			{
				if (obj != null)
				{
					UnityEvent onHurtColliderHit = obj.onHurtColliderHit;
					if (onHurtColliderHit != null)
					{
						onHurtColliderHit.RemoveListener(new UnityAction(OnHurtColliderHit));
					}
				}
			}
		}

		private void OnHurtColliderHit()
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_controller == (Object)null || _cooldown > 0f || !SemiFunc.IsMasterClientOrSingleplayer() || !_controller.TryClaimWeaponHit(ModEnemyWeaponDamage.CurrentClaimId))
			{
				return;
			}
			_cooldown = 0.16f;
			Vector3 val = ClosestPoint(((Component)this).transform.position);
			if (EnemyLabBridge.IsExecutionHitNear(val))
			{
				_controller.ExecuteForLab();
				return;
			}
			int num = ModEnemyWeaponDamage.CurrentOrFallback(Plugin.Settings.AnatomistDamagePerHit.Value);
			if (num > 0)
			{
				_controller.ReceiveWeaponHit(val, num);
			}
		}

		private void DetectExpandedBulletHit()
		{
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: 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_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_controller == (Object)null)
			{
				return;
			}
			if (_bulletFrame != Time.frameCount)
			{
				_bulletFrame = Time.frameCount;
				_bullets = Object.FindObjectsOfType<ItemGunBullet>();
			}
			_current.Clear();
			ItemGunBullet[] bullets = _bullets;
			foreach (ItemGunBullet val in bullets)
			{
				if ((Object)(object)val == (Object)null || (Object)(object)((Component)val).GetComponent<CarouselVisualBulletMarker>() != (Object)null || (Object)(object)val.hurtCollider == (Object)null || !((Component)val.hurtCollider).gameObject.activeInHierarchy)
				{
					continue;
				}
				int instanceID = ((Object)val).GetInstanceID();
				_current.Add(instanceID);
				Vector3 position = ((Component)val.hurtCollider).transform.position;
				Vector3 value;
				bool num = _previous.TryGetValue(instanceID, out value);
				_previous[instanceID] = position;
				if (!(num ? SegmentIntersects(value, position) : Within(position)) || !_controller.TryClaimWeaponHit(instanceID))
				{
					continue;
				}
				_cooldown = 0.22f;
				if (EnemyLabBridge.IsExecutionHitNear(position))
				{
					_controller.ExecuteForLab();
					return;
				}
				int num2 = ModEnemyWeaponDamage.Resolve(val.hurtCollider, Plugin.Settings.AnatomistDamagePerHit.Value);
				if (num2 > 0)
				{
					_controller.ReceiveWeaponHit(position, num2);
				}
				return;
			}
			if (_previous.Count <= _current.Count)
			{
				return;
			}
			List<int> list = null;
			foreach (int key in _previous.Keys)
			{
				if (!_current.Contains(key))
				{
					if (list == null)
					{
						list = new List<int>();
					}
					list.Add(key);
				}
			}
			foreach (int item in list ?? new List<int>())
			{
				_previous.Remove(item);
			}
		}

		private bool Within(Vector3 point)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Clamp(Plugin.Settings.AnatomistHitDetectionPadding.Value, 0.12f, 0.8f);
			float num2 = num * num;
			Renderer[] renderers = _renderers;
			foreach (Renderer val in renderers)
			{
				if ((Object)(object)val != (Object)null && val.enabled && ((Component)val).gameObject.activeInHierarchy)
				{
					Bounds bounds = val.bounds;
					if (((Bounds)(ref bounds)).SqrDistance(point) <= num2)
					{
						return true;
					}
				}
			}
			return false;
		}

		private bool SegmentIntersects(Vector3 start, Vector3 end)
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Clamp(Plugin.Settings.AnatomistHitDetectionPadding.Value, 0.12f, 0.8f);
			Renderer[] renderers = _renderers;
			foreach (Renderer val in renderers)
			{
				if (!((Object)(object)val == (Object)null) && val.enabled && ((Component)val).gameObject.activeInHierarchy)
				{
					Bounds bounds = val.bounds;
					((Bounds)(ref bounds)).Expand(num * 2f);
					if (SegmentIntersectsBounds(start, end, bounds))
					{
						return true;
					}
				}
			}
			return false;
		}

		private Vector3 ClosestPoint(Vector3 origin)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: 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_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: 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)
			Vector3 result = ((Component)this).transform.position;
			float num = float.PositiveInfinity;
			Renderer[] renderers = _renderers;
			foreach (Renderer val in renderers)
			{
				if (!((Object)(object)val == (Object)null) && val.enabled)
				{
					Bounds bounds = val.bounds;
					Vector3 val2 = ((Bounds)(ref bounds)).ClosestPoint(origin);
					Vector3 val3 = val2 - origin;
					float sqrMagnitude = ((Vector3)(ref val3)).sqrMagnitude;
					if (sqrMagnitude < num)
					{
						num = sqrMagnitude;
						result = val2;
					}
				}
			}
			return result;
		}

		private static bool SegmentIntersectsBounds(Vector3 start, Vector3 end, Bounds bounds)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = end - start;
			float num = 0f;
			float num2 = 1f;
			for (int i = 0; i < 3; i++)
			{
				float num3 = ((Vector3)(ref start))[i];
				float num4 = ((Vector3)(ref val))[i];
				Vector3 val2;
				if (Mathf.Abs(num4) < 1E-05f)
				{
					val2 = ((Bounds)(ref bounds)).min;
					if (!(num3 < ((Vector3)(ref val2))[i]))
					{
						val2 = ((Bounds)(ref bounds)).max;
						if (!(num3 > ((Vector3)(ref val2))[i]))
						{
							continue;
						}
					}
					return false;
				}
				float num5 = 1f / num4;
				val2 = ((Bounds)(ref bounds)).min;
				float num6 = (((Vector3)(ref val2))[i] - num3) * num5;
				val2 = ((Bounds)(ref bounds)).max;
				float num7 = (((Vector3)(ref val2))[i] - num3) * num5;
				if (num6 > num7)
				{
					float num8 = num7;
					num7 = num6;
					num6 = num8;
				}
				num = Mathf.Max(num, num6);
				num2 = Mathf.Min(num2, num7);
				if (num > num2)
				{
					return false;
				}
			}
			return true;
		}
	}
	internal sealed class AnatomistManager : MonoBehaviour
	{
		private int _levelId;

		private float _spawnTimer;

		private bool _attemptFinished;

		private bool _probed;

		private bool _available;

		private AnatomistController _encounter;

		internal void Tick()
		{
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			if (!IsHostReady())
			{
				return;
			}
			Probe();
			int num = (((Object)(object)LevelGenerator.Instance != (Object)null) ? ((Object)LevelGenerator.Instance).GetInstanceID() : 0);
			if (num != _levelId)
			{
				ResetForLevel(num);
			}
			if (!ModEnemyLevelRules.IsPlayableLevel())
			{
				DestroyCurrent();
				return;
			}
			LevelGenerator instance = LevelGenerator.Instance;
			if ((Object)(object)instance == (Object)null || !instance.Generated || _attemptFinished)
			{
				return;
			}
			_spawnTimer -= Time.deltaTime;
			if (!(_spawnTimer > 0f))
			{
				_attemptFinished = true;
				if (Random.value <= Mathf.Clamp01(Plugin.Settings.AnatomistSpawnChance.Value) && TryFindSpawn(out var position))
				{
					Create(position, "automatic");
				}
			}
		}

		private void ResetForLevel(int levelId)
		{
			DestroyCurrent();
			_levelId = levelId;
			_spawnTimer = Mathf.Max(0f, Plugin.Settings.AnatomistSpawnDelay.Value);
			_attemptFinished = false;
		}

		private bool Create(Vector3 position, string source)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			if (!_available && !AnatomistSpawner.PrefabsAvailable())
			{
				Plugin.Log.LogWarning((object)"The Anatomist could not resolve its vanilla syringe-arm resources.");
				return false;
			}
			DestroyCurrent();
			GameObject val = new GameObject("The Anatomist Encounter (Host Logic)");
			val.SetActive(false);
			val.transform.position = position;
			AnatomistController anatomistController = val.AddComponent<AnatomistController>();
			if (!anatomistController.Initialize(position))
			{
				Object.Destroy((Object)(object)val);
				return false;
			}
			val.SetActive(true);
			_encounter = anatomistController;
			Plugin.Log.LogInfo((object)$"The Anatomist descended at {position} ({source}); all visible arm and dummy-head pieces are vanilla network objects.");
			return true;
		}

		internal bool DebugSpawnAt(Vector3 requestedPosition)
		{
			//IL_0039: 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)
			if (!IsHostReady() || (!ModEnemySpawnCoordinator.IsDirectorRequestActive && (Object)(object)PlayerAvatar.instance == (Object)null) || !ModEnemyLevelRules.IsPlayableLevel())
			{
				Plugin.Log.LogWarning((object)"Enemy Lab rejected The Anatomist because no playable host level is active.");
				return false;
			}
			Probe();
			NavMeshHit val = default(NavMeshHit);
			if (!NavMesh.SamplePosition(requestedPosition, ref val, 12f, -1))
			{
				return false;
			}
			_attemptFinished = true;
			return Create(((NavMeshHit)(ref val)).position, ModEnemySpawnCoordinator.CurrentSpawnSource);
		}

		internal void MarkAutomaticAttemptFinished()
		{
			int num = (((Object)(object)LevelGenerator.Instance != (Object)null) ? ((Object)LevelGenerator.Instance).GetInstanceID() : 0);
			if (num != _levelId)
			{
				ResetForLevel(num);
			}
			_attemptFinished = true;
		}

		internal void DebugDespawn()
		{
			if (IsHostReady())
			{
				_attemptFinished = true;
				DestroyCurrent();
			}
		}

		private void DestroyCurrent()
		{
			if ((Object)(object)_encounter != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)_encounter).gameObject);
				_encounter = null;
			}
		}

		private void Probe()
		{
			if (!_probed && !((Object)(object)RunManager.instance == (Object)null))
			{
				_probed = true;
				_available = AnatomistSpawner.PrefabsAvailable();
				Plugin.Log.LogInfo((object)$"The Anatomist prefab probe: available={_available}.");
			}
		}

		private static bool TryFindSpawn(out Vector3 position)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: 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_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			position = Vector3.zero;
			PlayerAvatar val = null;
			foreach (PlayerAvatar item in SemiFunc.PlayerGetList())
			{
				if (GunAccess.IsLiving(item))
				{
					val = item;
					break;
				}
			}
			Vector3 val2 = (((Object)(object)val != (Object)null) ? ((Component)val).transform.position : Vector3.zero);
			LevelPoint val3 = SemiFunc.LevelPointGetPlayerDistance(val2, 20f, 65f, false) ?? SemiFunc.LevelPointGetFurthestFromPlayer(val2, 8f);
			return ModEnemyNavigation.TryFindClearSpawn(((Object)(object)val3 != (Object)null) ? ((Component)val3).transform.position : (val2 + Vector3.forward * 20f), 8f, out position);
		}

		private static bool IsHostReady()
		{
			try
			{
				return (Object)(object)GameManager.instance != (Object)null && (!GameManager.Multiplayer() || PhotonNetwork.IsMasterClient);
			}
			catch
			{
				return false;
			}
		}
	}
	internal enum AnatomistPartRole
	{
		Cable,
		Cable1,
		Cable2,
		Cable3,
		Cable4,
		Cable5,
		Cable6,
		Cable7,
		Cable8,
		Cable9,
		Cable10,
		Cable11,
		Cable12,
		Cable13,
		Cable14,
		Cable15,
		Cable16,
		Cable17,
		Cable18,
		Cable19,
		Cable20,
		Cable21,
		Cable22,
		Cable23,
		Cable24,
		Cable25,
		Palm,
		FingerBarrel0,
		FingerBarrel1,
		FingerBarrel2,
		FingerBarrel3,
		FingerBarrel4,
		Needle0,
		Needle1,
		Needle2,
		Needle3,
		Needle4,
		DummyHead
	}
	internal sealed class SpawnedAnatomistPart
	{
		internal string ResourcePath;

		internal GameObject Root;

		internal PhysGrabObject Phys;

		internal PhysGrabObjectImpactDetector ImpactDetector;

		internal ItemAttributes Attributes;

		internal PhotonView View;

		internal Renderer[] Renderers;

		internal Collider[] Colliders;

		internal AnatomistPartRole Role;

		internal Vector3 VisualCenterOffset;

		internal Vector3 VisualSize;

		internal Vector3 LongAxisLocal = Vector3.up;

		internal int GeometryCalibrationFrames = 16;

		internal Vector3 SmoothedVisualCenter;

		internal Quaternion SmoothedRotation = Quaternion.identity;

		internal bool PoseInitialized;

		internal PlayerDeathHead DeathHead;

		internal Vector3 HeadSpawnPosition;

		internal Quaternion HeadSpawnRotation = Quaternion.identity;

		internal float HeadActivationTimer;

		internal int HeadActivationRepeats;

		internal bool HeadActivated;

		internal int HeadColorIndex = -1;

		internal bool HeadColorSent;

		internal bool HeadDiscovered;

		internal bool HeadHostDiscoverGraphicShown;

		internal bool GeometryLogged;

		internal bool Alive = true;
	}
	internal static class AnatomistSpawner
	{
		private static readonly string[] SizeFolders = new string[7] { "01 Tiny", "02 Small", "03 Medium", "04 Big", "05 Wide", "06 Tall", "07 Very Tall" };

		private static string _palmPath;

		private static string _fingerPath;

		internal static string CableResourcePath => "Valuables/07 Very Tall/Valuable Wizard Broom";

		internal static string PalmResourcePath
		{
			get
			{
				object obj = _palmPath;
				if (obj == null)
				{
					obj = FindValuable("Valuable Arctic HDD") ?? FindValuable("Valuable Arctic Phone") ?? FindValuable("Valuable Arctic Pills") ?? "Valuables/07 Very Tall/Valuable Wizard Broom";
					_palmPath = (string)obj;
				}
				return (string)obj;
			}
		}

		internal static string FingerResourcePath
		{
			get
			{
				object obj = _fingerPath;
				if (obj == null)
				{
					obj = FindValuable("Valuable Arctic Icepick") ?? FindValuable("Valuable Arctic Ice Pick") ?? FindValuable("Valuable Icepick") ?? FindValuable("Valuable Ice Pick") ?? FindValuable("Valuable Wizard Unicorn Horn") ?? "Valuables/07 Very Tall/Valuable Wizard Broom";
					_fingerPath = (string)obj;
				}
				return (string)obj;
			}
		}

		internal static bool PrefabsAvailable()
		{
			if ((Object)(object)Resources.Load<GameObject>(CableResourcePath) != (Object)null && (Object)(object)Resources.Load<GameObject>(PalmResourcePath) != (Object)null)
			{
				return (Object)(object)Resources.Load<GameObject>(FingerResourcePath) != (Object)null;
			}
			return false;
		}

		private static string FindValuable(string name)
		{
			string[] sizeFolders = SizeFolders;
			foreach (string text in sizeFolders)
			{
				string text2 = "Valuables/" + text + "/" + name;
				if ((Object)(object)Resources.Load<GameObject>(text2) != (Object)null)
				{
					return text2;
				}
			}
			return null;
		}

		internal static SpawnedAnatomistPart SpawnBodyPart(string resourcePath, Vector3 position, Vector3 scale, AnatomistPartRole role)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			SpawnedAnatomistPart spawnedAnatomistPart = Spawn(resourcePath, position, scale, role);
			if (spawnedAnatomistPart == null)
			{
				return null;
			}
			EncounterValuableNeutralizer.Apply(spawnedAnatomistPart.Root);
			ItemAttributes attributes = spawnedAnatomistPart.Attributes;
			if (attributes != null)
			{
				attributes.DisableUI(true);
			}
			spawnedAnatomistPart.ImpactDetector.destroyDisable = true;
			spawnedAnatomistPart.ImpactDetector.playerHurtDisable = true;
			spawnedAnatomistPart.Phys.OverrideIndestructible(1f);
			spawnedAnatomistPart.Phys.OverrideGrabDisable(1f);
			spawnedAnatomistPart.Phys.OverrideKinematic(1f);
			MapIconSuppressor.Attach(spawnedAnatomistPart.Root);
			return spawnedAnatomistPart;
		}

		internal static SpawnedAnatomistPart SpawnDummyHead(Vector3 position)
		{
			//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_0077: 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_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: 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)
			GameObject val = LevelGenerator.Instance?.PlayerDeathHeadPrefab;
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogWarning((object)"The Anatomist could not find the vanilla PlayerDeathHead prefab.");
				return null;
			}
			try
			{
				Quaternion val2 = Quaternion.Euler(Random.Range(-24f, 24f), Random.Range(0f, 360f), Random.Range(-18f, 18f));
				GameObject val3 = (GameManager.Multiplayer() ? PhotonNetwork.Instantiate(((Object)val).name, position, val2, (byte)0, (object[])null) : Object.Instantiate<GameObject>(val, position, val2));
				if ((Object)(object)val3 == (Object)null)
				{
					return null;
				}
				PlayerDeathHead component = val3.GetComponent<PlayerDeathHead>();
				if ((Object)(object)component != (Object)null)
				{
					((Behaviour)component).enabled = false;
					Traverse.Create((object)component).Field("setup").SetValue((object)true);
				}
				SpawnedAnatomistPart spawnedAnatomistPart = new SpawnedAnatomistPart
				{
					ResourcePath = ((Object)val).name,
					Root = val3,
					Phys = val3.GetComponentInChildren<PhysGrabObject>(true),
					ImpactDetector = val3.GetComponentInChildren<PhysGrabObjectImpactDetector>(true),
					View = val3.GetComponentInChildren<PhotonView>(true),
					Renderers = val3.GetComponentsInChildren<Renderer>(true),
					Colliders = val3.GetComponentsInChildren<Collider>(true),
					Role = AnatomistPartRole.DummyHead,
					DeathHead = component,
					HeadSpawnPosition = position,
					HeadSpawnRotation = val2,
					HeadActivationTimer = 0.45f,
					HeadActivationRepeats = 4,
					HeadColorIndex = ((MetaManager.instance?.colors != null && MetaManager.instance.colors.Count > 0) ? Random.Range(0, MetaManager.instance.colors.Count) : 0)
				};
				if ((Object)(object)spawnedAnatomistPart.Phys == (Object)null || (Object)(object)spawnedAnatomistPart.ImpactDetector == (Object)null)
				{
					Destroy(spawnedAnatomistPart);
					return null;
				}
				spawnedAnatomistPart.ImpactDetector.destroyDisable = true;
				spawnedAnatomistPart.ImpactDetector.playerHurtDisable = true;
				spawnedAnatomistPart.Phys.clientNonKinematic = true;
				spawnedAnatomistPart.Phys.OverrideMass(1.1f, 1f);
				PlayerCosmetics[] componentsInChildren = val3.GetComponentsInChildren<PlayerCosmetics>(true);
				foreach (PlayerCosmetics val4 in componentsInChildren)
				{
					if (!((Object)(object)val4 == (Object)null))
					{
						TryApplyHostDummyColour(val4, component, spawnedAnatomistPart.Phys, spawnedAnatomistPart.HeadColorIndex);
						Traverse.Create((object)val4).Field("firstSetup").SetValue((object)false);
						((Behaviour)val4).enabled = false;
					}
				}
				return spawnedAnatomistPart;
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"The Anatomist could not spawn a vanilla player head: {arg}");
				return null;
			}
		}

		private static void TryApplyHostDummyColour(PlayerCosmetics cosmetics, PlayerDeathHead deathHead, PhysGrabObject phys, int colour)
		{
			if ((Object)(object)cosmetics == (Object)null || (Object)(object)deathHead == (Object)null || (Object)(object)phys == (Object)null || MetaManager.instance?.colors == null || MetaManager.instance.colors.Count == 0)
			{
				return;
			}
			try
			{
				Traverse.Create((object)deathHead).Field("physGrabObject").SetValue((object)phys);
				Traverse.Create((object)cosmetics).Method("PlayerMaterialSetup", Array.Empty<object>()).GetValue();
				colour = Mathf.Clamp(colour, 0, MetaManager.instance.colors.Count - 1);
				Traverse.Create((object)cosmetics).Method("SetupColorsAllLogic", new object[1] { colour }).GetValue();
			}
			catch (Exception ex)
			{
				Plugin.Log.LogDebug((object)("The Anatomist kept the host dummy head's default colour: " + ex.Message));
			}
		}

		private static SpawnedAnatomistPart Spawn(string resourcePath, Vector3 position, Vector3 scale, AnatomistPartRole role)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: 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_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: 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_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Resources.Load<GameObject>(resourcePath);
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogWarning((object)("The Anatomist could not load vanilla resource '" + resourcePath + "'."));
				return null;
			}
			((Vector3)(ref scale))..ctor(Mathf.Clamp(scale.x, 0.025f, 1.5f), Mathf.Clamp(scale.y, 0.025f, 1.5f), Mathf.Clamp(scale.z, 0.025f, 1.5f));
			Vector3 val2 = Vector3.Scale(val.transform.localScale, scale);
			object[] array = new object[3] { val2.x, val2.y, val2.z };
			GameObject val3;
			try
			{
				val3 = (GameManager.Multiplayer() ? PhotonNetwork.InstantiateRoomObject(resourcePath, position, Quaternion.identity, (byte)0, array) : Object.Instantiate<GameObject>(val, position, Quaternion.identity));
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"The Anatomist failed to network-spawn '{resourcePath}': {arg}");
				return null;
			}
			if ((Object)(object)val3 == (Object)null)
			{
				return null;
			}
			val3.transform.localScale = val2;
			SpawnedAnatomistPart spawnedAnatomistPart = new SpawnedAnatomistPart
			{
				ResourcePath = resourcePath,
				Root = val3,
				Phys = val3.GetComponentInChildren<PhysGrabObject>(true),
				ImpactDetector = val3.GetComponentInChildren<PhysGrabObjectImpactDetector>(true),
				Attributes = val3.GetComponentInChildren<ItemAttributes>(true),
				View = val3.GetComponentInChildren<PhotonView>(true),
				Renderers = val3.GetComponentsInChildren<Renderer>(true),
				Colliders = val3.GetComponentsInChildren<Collider>(true),
				Role = role
			};
			if ((Object)(object)spawnedAnatomistPart.Phys == (Object)null || (Object)(object)spawnedAnatomistPart.ImpactDetector == (Object)null)
			{
				Plugin.Log.LogError((object)("The Anatomist resource '" + resourcePath + "' lacks vanilla physical components."));
				Destroy(spawnedAnatomistPart);
				return null;
			}
			RefreshGeometry(spawnedAnatomistPart);
			return spawnedAnatomistPart;
		}

		internal static void RefreshGeometry(SpawnedAnatomistPart part, bool refreshLongAxis = true)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: 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_0084: 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_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: 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)
			if ((Object)(object)part?.Phys == (Object)null || part.Renderers == null)
			{
				return;
			}
			bool flag = false;
			Bounds val = default(Bounds);
			Renderer[] renderers = part.Renderers;
			foreach (Renderer val2 in renderers)
			{
				if ((Object)(object)val2 == (Object)null || !val2.enabled || (!(val2 is MeshRenderer) && !(val2 is SkinnedMeshRenderer)))
				{
					continue;
				}
				Bounds bounds = val2.bounds;
				Vector3 size = ((Bounds)(ref bounds)).size;
				if (!(((Vector3)(ref size)).sqrMagnitude < 1E-06f) && !(((Bounds)(ref bounds)).size.x > 10f) && !(((Bounds)(ref bounds)).size.y > 10f) && !(((Bounds)(ref bounds)).size.z > 10f))
				{
					if (!flag)
					{
						val = bounds;
						flag = true;
					}
					else
					{
						((Bounds)(ref val)).Encapsulate(bounds);
					}
				}
			}
			if (flag)
			{
				part.VisualCenterOffset = Quaternion.Inverse(((Component)part.Phys).transform.rotation) * (((Bounds)(ref val)).center - ((Component)part.Phys).transform.position);
				part.VisualSize = ((Bounds)(ref val)).size;
				if (refreshLongAxis)
				{
					Vector3 val3 = ((Component)part.Phys).transform.InverseTransformDirection(Vector3.right);
					Vector3 val4 = ((Component)part.Phys).transform.InverseTransformDirection(Vector3.up);
					Vector3 val5 = ((Component)part.Phys).transform.InverseTransformDirection(Vector3.forward);
					part.LongAxisLocal = ((((Bounds)(ref val)).size.x >= ((Bounds)(ref val)).size.y && ((Bounds)(ref val)).size.x >= ((Bounds)(ref val)).size.z) ? val3 : ((((Bounds)(ref val)).size.y >= ((Bounds)(ref val)).size.z) ? val4 : val5));
				}
			}
		}

		internal static void Destroy(SpawnedAnatomistPart part)
		{
			if (part == null)
			{
				return;
			}
			if ((Object)(object)part.Root == (Object)null)
			{
				part.Alive = false;
				return;
			}
			if (GameManager.Multiplayer())
			{
				PhotonNetwork.Destroy(part.Root);
			}
			else
			{
				Object.Destroy((Object)(object)part.Root);
			}
			part.Alive = false;
		}
	}
	internal sealed class AuditorController : MonoBehaviour, IModEnemyTumbleReceiver
	{
		private sealed class UpgradeDefinition
		{
			internal readonly string CommandName;

			internal readonly string ResourcePath;

			internal readonly Func<StatsManager, Dictionary<string, int>> Levels;

			internal UpgradeDefinition(string commandName, string resourcePath, Func<StatsManager, Dictionary<string, int>> levels)
			{
				CommandName = commandName;
				ResourcePath = resourcePath;
				Levels = levels;
			}
		}

		private static readonly UpgradeDefinition[] UpgradeDefinitions = new UpgradeDefinition[13]
		{
			new UpgradeDefinition("CrouchRest", "Items/Item Upgrade Player Crouch Rest", (StatsManager stats) => stats.playerUpgradeCrouchRest),
			new UpgradeDefinition("DeathHeadBattery", "Items/Item Upgrade Death Head Battery", (StatsManager stats) => stats.playerUpgradeDeathHeadBattery),
			new UpgradeDefinition("ExtraJump", "Items/Item Upgrade Player Extra Jump", (StatsManager stats) => stats.playerUpgradeExtraJump),
			new UpgradeDefinition("Health", "Items/Item Upgrade Player Health", (StatsManager stats) => stats.playerUpgradeHealth),
			new UpgradeDefinition("Launch", "Items/Item Upgrade Player Tumble Launch", (StatsManager stats) => stats.playerUpgradeLaunch),
			new UpgradeDefinition("MapPlayerCount", "Items/Item Upgrade Map Player Count", (StatsManager stats) => stats.playerUpgradeMapPlayerCount),
			new UpgradeDefinition("Range", "Items/Item Upgrade Player Grab Range", (StatsManager stats) => stats.playerUpgradeRange),
			new UpgradeDefinition("Speed", "Items/Item Upgrade Player Sprint Speed", (StatsManager stats) => stats.playerUpgradeSpeed),
			new UpgradeDefinition("Stamina", "Items/Item Upgrade Player Energy", (StatsManager stats) => stats.playerUpgradeStamina),
			new UpgradeDefinition("Strength", "Items/Item Upgrade Player Grab Strength", (StatsManager stats) => stats.playerUpgradeStrength),
			new UpgradeDefinition("Throw", "Items/Item Upgrade Player Grab Throw", (StatsManager stats) => stats.p