Decompiled source of CrewMonitors v1.0.33

CrewMonitors.dll

Decompiled 3 weeks 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.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using OpenBodyCams;
using OpenBodyCams.API;
using TMPro;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Rendering;
using UnityEngine.UI;

[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("CrewMonitors")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.33.0")]
[assembly: AssemblyInformationalVersion("1.0.33+4c7fb8c0ca25ed457152595237a7b526820834c9")]
[assembly: AssemblyProduct("CrewMonitors")]
[assembly: AssemblyTitle("CrewMonitors")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.33.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 CrewMonitors
{
	public sealed class CrewMonitorManager : MonoBehaviour
	{
		private struct WallPlacement
		{
			public int HorizontalAxis;

			public int VerticalAxis;

			public int DepthAxis;

			public float HSign;

			public float VSign;

			public float OutwardSign;

			public float FlushDepth;

			public Bounds LocalBounds;

			public bool MaxIsOutward;
		}

		private sealed class CrewSlot
		{
			public int Index;

			public GameObject Host;

			public MeshRenderer Renderer;

			public BodyCamComponent BodyCam;

			public Material? OriginalOffMaterial;

			public bool IsClone;

			public PlayerControllerB? AssignedPlayer;

			public int CycleIndex;

			public bool UserCycled;

			public bool ShowMapFeed;

			public Camera? MapFeedCamera;

			public RenderTexture? MapFeedTexture;

			public TextMeshPro? Nameplate;

			public GameObject? CycleButton;

			public GameObject? FocusTrigger;
		}

		private const int CycleOff = -2;

		private const int CycleExternal = -1;

		private const string MonitorWallPath = "Environment/HangarShip/ShipModels2b/MonitorWall";

		private const string SingleScreenPath = "Environment/HangarShip/ShipModels2b/MonitorWall/SingleScreen";

		private const string MainWallCubeName = "Cube.001";

		private const string ClonePrefix = "CrewMonitor_Clone_";

		private const string SlotRootName = "CrewMonitors_Root";

		private const string QuadTemplateName = "CrewMonitors_QuadTemplate";

		private const float SingleScreenScaleAtDefaultFactor = 2f;

		private const float DefaultCloneScaleFactor = 0.6f;

		private const float MapCameraYOffset = 3.636f;

		private const float MapCameraNearDefault = -2.47f;

		private const float MapCameraFarDefault = 7.52f;

		private static readonly string[] RejectNameTokens = new string[6] { "Button", "Overlay", "Switch", "OnButton", "CameraMonitorOn", "CameraMonitorSwitch" };

		private static readonly string[] AxisNames = new string[3] { "X", "Y", "Z" };

		private readonly List<CrewSlot> _slots = new List<CrewSlot>();

		private Transform? _monitorWall;

		private Transform? _placementAnchor;

		private MeshRenderer? _anchorRenderer;

		private MeshRenderer? _cloneTemplate;

		private GameObject? _ownedQuadTemplate;

		private WallPlacement _wallPlacement;

		private bool _wallPlacementValid;

		private GameObject? _slotRoot;

		private bool _setupStarted;

		private bool _setupComplete;

		private bool _refreshRequested;

		private bool _setupSoonRequested;

		private float _refreshTimer;

		private float _setupWaitElapsed;

		private static readonly BindingFlags BodyCamFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

		private static Material? _blackScreenMaterial;

		private static Sprite? _transparentHoverIcon;

		internal static CrewMonitorManager? Instance { get; private set; }

		private void Awake()
		{
			Instance = this;
		}

		private void OnDestroy()
		{
			if ((Object)(object)Instance == (Object)(object)this)
			{
				Instance = null;
			}
			TeardownSlots();
			if ((Object)(object)_ownedQuadTemplate != (Object)null)
			{
				Object.Destroy((Object)(object)_ownedQuadTemplate);
				_ownedQuadTemplate = null;
			}
		}

		private void Start()
		{
			((MonoBehaviour)this).StartCoroutine(SetupWhenReady());
		}

		private void Update()
		{
			if (!Plugin.Enabled.Value)
			{
				if (_slots.Count > 0)
				{
					PowerDownAll();
				}
				return;
			}
			if (_setupSoonRequested && !_setupComplete)
			{
				_setupSoonRequested = false;
				if (!_setupStarted)
				{
					((MonoBehaviour)this).StartCoroutine(SetupWhenReady());
				}
			}
			if (_setupComplete)
			{
				float num = Mathf.Max(0.25f, Plugin.RefreshSeconds.Value);
				_refreshTimer += Time.deltaTime;
				if (_refreshRequested || _refreshTimer >= num)
				{
					_refreshRequested = false;
					_refreshTimer = 0f;
					RefreshAssignments();
				}
			}
		}

		private void LateUpdate()
		{
			if (!Plugin.Enabled.Value || !_setupComplete)
			{
				return;
			}
			foreach (CrewSlot slot in _slots)
			{
				if ((Object)(object)slot.BodyCam == (Object)null)
				{
					continue;
				}
				if (slot.ShowMapFeed && (Object)(object)slot.AssignedPlayer != (Object)null)
				{
					UpdateMapFeedFollow(slot);
					ApplyMapFeedTextureToMonitor(slot);
					continue;
				}
				PlayerControllerB val = (((Object)(object)slot.AssignedPlayer != (Object)null && IsLivingPlayer(slot.AssignedPlayer)) ? slot.AssignedPlayer : null);
				if (!((Object)(object)slot.BodyCam.CurrentPlayerTarget == (Object)(object)val))
				{
					if ((Object)(object)val != (Object)null)
					{
						slot.BodyCam.SetTargetToPlayer(val);
					}
					else
					{
						slot.BodyCam.SetTargetToNone();
					}
				}
			}
		}

		internal void RequestRefresh()
		{
			_refreshRequested = true;
		}

		internal void RequestSetupSoon()
		{
			_setupSoonRequested = true;
		}

		private IEnumerator SetupWhenReady()
		{
			if (_setupStarted)
			{
				yield break;
			}
			_setupStarted = true;
			_setupWaitElapsed = 0f;
			while (_setupWaitElapsed < 12f)
			{
				GameObject val = GameObject.Find("Environment/HangarShip/ShipModels2b/MonitorWall");
				bool flag = (Object)(object)BodyCam.MainBodyCam != (Object)null || BodyCamComponent.GetAllBodyCams().Length != 0;
				if ((Object)(object)val != (Object)null && (flag || _setupWaitElapsed > 3f))
				{
					_monitorWall = val.transform;
					break;
				}
				_setupWaitElapsed += 0.25f;
				yield return (object)new WaitForSeconds(0.25f);
			}
			if ((Object)(object)_monitorWall == (Object)null)
			{
				Plugin.Log.LogWarning((object)"MonitorWall not found; crew monitors will not set up.");
				yield break;
			}
			try
			{
				BuildSlots();
				_setupComplete = true;
				RefreshAssignments();
				Plugin.Log.LogInfo((object)$"Crew monitors ready with {_slots.Count} slot(s).");
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"Crew monitor setup failed: {arg}");
			}
		}

		private void BuildSlots()
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			//IL_004a: 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_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0183: 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_0191: 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_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0216: Unknown result type (might be due to invalid IL or missing references)
			//IL_0365: Unknown result type (might be due to invalid IL or missing references)
			//IL_036c: Unknown result type (might be due to invalid IL or missing references)
			TeardownSlots();
			int num = Mathf.Clamp(Plugin.MaxMonitors.Value, 1, 8);
			_slotRoot = new GameObject("CrewMonitors_Root");
			_slotRoot.transform.SetParent(_monitorWall, false);
			_slotRoot.transform.localPosition = Vector3.zero;
			_slotRoot.transform.localRotation = Quaternion.identity;
			_slotRoot.transform.localScale = Vector3.one;
			ResolvePlacementAnchor();
			_wallPlacementValid = TryComputeWallPlacement(out _wallPlacement);
			List<MeshRenderer> list = CollectReusableRenderers();
			EnsureCloneTemplate(list);
			int num2 = 0;
			for (int i = 0; i < num; i++)
			{
				MeshRenderer renderer = null;
				bool flag = false;
				GameObject val;
				if (i < list.Count)
				{
					renderer = list[i];
					val = ((Component)renderer).gameObject;
				}
				else
				{
					if ((Object)(object)_cloneTemplate == (Object)null)
					{
						Plugin.Log.LogWarning((object)"No template MeshRenderer available to clone; stopping slot creation.");
						break;
					}
					val = CloneMonitor(num2, out renderer);
					num2++;
					flag = true;
					if ((Object)(object)renderer == (Object)null)
					{
						break;
					}
				}
				int num3 = PickMaterialIndex(renderer);
				IsolateScreenMaterial(renderer, num3);
				BodyCamComponent val2;
				try
				{
					val2 = BodyCam.CreateBodyCam(val, (Renderer)(object)renderer, num3, (ManualCameraRenderer)null);
				}
				catch (Exception ex)
				{
					Plugin.Log.LogError((object)$"CreateBodyCam failed for slot {i} on {((Object)val).name}: {ex.Message}");
					if (flag)
					{
						Object.Destroy((Object)(object)val);
					}
					continue;
				}
				try
				{
					float num4 = 1.3333334f;
					Bounds localBounds = ((Renderer)renderer).localBounds;
					Vector3 size = ((Bounds)(ref localBounds)).size;
					float num5 = Mathf.Max(size.x, Mathf.Max(size.y, size.z));
					float num6 = Mathf.Min(size.x, Mathf.Min(size.y, size.z));
					if (num5 > 0.001f && num6 > 0.001f)
					{
						num4 = Mathf.Clamp(num5 / Mathf.Max(0.001f, num6), 0.5f, 3f);
					}
					int num7 = Mathf.Max(90, Mathf.RoundToInt(480f / num4));
					val2.Resolution = new Vector2Int(480, num7);
				}
				catch (Exception ex2)
				{
					Plugin.Log.LogWarning((object)("Set Resolution 480 failed: " + ex2.Message));
				}
				val2.SetTargetToNone();
				val2.SetScreenPowered(false);
				try
				{
					val2.UpdateScreenMaterial();
				}
				catch
				{
				}
				ApplyScreenBrightness(val2);
				CrewSlot crewSlot = new CrewSlot
				{
					Index = i,
					Host = val,
					Renderer = renderer,
					BodyCam = val2,
					IsClone = flag,
					OriginalOffMaterial = GetMonitorOffMaterial(val2),
					CycleIndex = -2,
					UserCycled = false,
					Nameplate = (Plugin.ShowNameplates.Value ? CreateNameplate(val, renderer) : null)
				};
				_slots.Add(crewSlot);
				SetupSlotInteractions(crewSlot);
				Vector3 localPosition = val.transform.localPosition;
				Vector3 position = val.transform.position;
				string text = (flag ? "clone" : "reuse");
				ManualLogSource log = Plugin.Log;
				object[] obj2 = new object[4]
				{
					i,
					text,
					((Object)val).name,
					null
				};
				Transform parent = val.transform.parent;
				obj2[3] = ((parent != null) ? ((Object)parent).name : null) ?? "none";
				log.LogInfo((object)(string.Format("Slot {0} ({1}): {2} parent={3} ", obj2) + $"local={localPosition} world={position} path={GetPath(val.transform)}"));
			}
		}

		private void ResolvePlacementAnchor()
		{
			//IL_005a: 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_0077: 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)
			_placementAnchor = null;
			_anchorRenderer = null;
			if (!((Object)(object)_monitorWall == (Object)null))
			{
				Transform val = _monitorWall.Find("Cube.001");
				if ((Object)(object)val != (Object)null)
				{
					_placementAnchor = val;
					_anchorRenderer = ((Component)val).GetComponent<MeshRenderer>();
					ManualLogSource log = Plugin.Log;
					string text = string.Format("Clone placement anchor: {0} localPos={1} ", "Cube.001", val.localPosition);
					Quaternion localRotation = val.localRotation;
					log.LogInfo((object)(text + $"localRot={((Quaternion)(ref localRotation)).eulerAngles} localScale={val.localScale}"));
				}
				else
				{
					_placementAnchor = _monitorWall;
					_anchorRenderer = ((Component)_monitorWall).GetComponent<MeshRenderer>();
					Plugin.Log.LogInfo((object)"Clone placement anchor: MonitorWall origin (no Cube.001 found)");
				}
			}
		}

		private bool TryComputeWallPlacement(out WallPlacement wp)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: 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_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: 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_00ba: 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)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: 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_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: 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_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: 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_021c: 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_0225: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0249: Unknown result type (might be due to invalid IL or missing references)
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_025c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0261: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e1: 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_030b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0315: Unknown result type (might be due to invalid IL or missing references)
			//IL_031d: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: Unknown result type (might be due to invalid IL or missing references)
			wp = default(WallPlacement);
			if ((Object)(object)_placementAnchor == (Object)null)
			{
				return false;
			}
			MeshRenderer val = _anchorRenderer ?? ((Component)_placementAnchor).GetComponent<MeshRenderer>();
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogWarning((object)"Placement anchor has no MeshRenderer; cannot compute wall bounds/depth.");
				return false;
			}
			Bounds localBounds = ((Renderer)val).localBounds;
			Vector3 size = ((Bounds)(ref localBounds)).size;
			int num = 0;
			if (size.y <= size.x && size.y <= size.z)
			{
				num = 1;
			}
			else if (size.z <= size.x && size.z <= size.y)
			{
				num = 2;
			}
			int num2 = (num + 1) % 3;
			int num3 = (num + 2) % 3;
			Vector3 val2 = _placementAnchor.TransformDirection(AxisUnit(num2));
			Vector3 normalized = ((Vector3)(ref val2)).normalized;
			val2 = _placementAnchor.TransformDirection(AxisUnit(num3));
			Vector3 normalized2 = ((Vector3)(ref val2)).normalized;
			int num4;
			int num5;
			if (Mathf.Abs(Vector3.Dot(normalized, Vector3.up)) >= Mathf.Abs(Vector3.Dot(normalized2, Vector3.up)))
			{
				num4 = num2;
				num5 = num3;
			}
			else
			{
				num4 = num3;
				num5 = num2;
			}
			val2 = _placementAnchor.TransformDirection(AxisUnit(num5));
			Vector3 normalized3 = ((Vector3)(ref val2)).normalized;
			val2 = _placementAnchor.TransformDirection(AxisUnit(num4));
			Vector3 normalized4 = ((Vector3)(ref val2)).normalized;
			float num6 = ((Vector3.Dot(normalized3, Vector3.right) >= 0f) ? 1f : (-1f));
			float num7 = ((Vector3.Dot(normalized4, Vector3.up) >= 0f) ? 1f : (-1f));
			Vector3 val3 = _placementAnchor.TransformPoint(((Bounds)(ref localBounds)).center);
			Vector3 val4 = val3;
			GameObject val5 = GameObject.Find("Environment/HangarShip");
			if ((Object)(object)val5 != (Object)null)
			{
				val4 = val5.transform.position;
			}
			Vector3 val6 = val4 - val3;
			if (((Vector3)(ref val6)).sqrMagnitude < 1E-06f)
			{
				val6 = (((Object)(object)_monitorWall != (Object)null) ? (-_monitorWall.forward) : Vector3.forward);
			}
			((Vector3)(ref val6)).Normalize();
			val2 = _placementAnchor.TransformDirection(AxisUnit(num));
			bool flag = Vector3.Dot(((Vector3)(ref val2)).normalized, val6) > 0f;
			float num8 = (flag ? 1f : (-1f));
			val2 = ((Bounds)(ref localBounds)).extents;
			float num9 = ((Vector3)(ref val2))[num];
			val2 = ((Bounds)(ref localBounds)).center;
			float num10 = ((Vector3)(ref val2))[num] + num8 * num9;
			float num11 = Mathf.Clamp(Plugin.WallInset.Value, -1f, 1.5f);
			float num12 = num10 - num8 * num11;
			wp = new WallPlacement
			{
				HorizontalAxis = num5,
				VerticalAxis = num4,
				DepthAxis = num,
				HSign = num6,
				VSign = num7,
				OutwardSign = num8,
				FlushDepth = num12,
				LocalBounds = localBounds,
				MaxIsOutward = flag
			};
			Plugin.Log.LogInfo((object)($"Wall placement bounds: center={((Bounds)(ref localBounds)).center} size={size} extents={((Bounds)(ref localBounds)).extents} " + $"depthAxis={AxisNames[num]} (thin) horizAxis={AxisNames[num5]} (sign={num6}) " + $"vertAxis={AxisNames[num4]} (sign={num7}) maxIsOutward={flag} " + $"outwardSign={num8} front={num10} flushDepth={num12} inset={num11} " + $"cabinHint={val4} wallCenterWorld={val3}"));
			return true;
		}

		private static Vector3 AxisUnit(int axis)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			return (Vector3)(axis switch
			{
				0 => Vector3.right, 
				1 => Vector3.up, 
				_ => Vector3.forward, 
			});
		}

		private List<MeshRenderer> CollectReusableRenderers()
		{
			List<MeshRenderer> result = new List<MeshRenderer>();
			HashSet<int> claimed = new HashSet<int>();
			if (!Plugin.PreferReuseVanillaScreens.Value)
			{
				Plugin.Log.LogInfo((object)"PreferReuseVanillaScreens=false; building clone grid only (vanilla door/internal cams left alone).");
				return result;
			}
			GameObject val = GameObject.Find("Environment/HangarShip/ShipModels2b/MonitorWall/SingleScreen");
			TryAdd(((Object)(object)val != (Object)null) ? val.GetComponent<MeshRenderer>() : null, "SingleScreen");
			StartOfRound instance = StartOfRound.Instance;
			if ((Object)(object)instance != (Object)null)
			{
				MeshRenderer val2 = (((Object)(object)instance.insideCameraScreen != (Object)null) ? instance.insideCameraScreen.mesh : null);
				if ((Object)(object)val2 != (Object)null && ((Object)((Component)val2).gameObject).name != "Cube.001" && !((Object)((Component)val2).gameObject).name.Contains("Cube.001"))
				{
					TryAdd(val2, "insideCameraScreen.mesh");
				}
				else if ((Object)(object)val2 != (Object)null)
				{
					Plugin.Log.LogDebug((object)("Skipping insideCameraScreen.mesh (" + ((Object)val2).name + "): Cube.001 / main wall."));
				}
				MeshRenderer val3 = (((Object)(object)instance.securityCameraScreen != (Object)null) ? instance.securityCameraScreen.mesh : null);
				if ((Object)(object)val3 != (Object)null && (((Object)((Component)val3).gameObject).name == "Cube.001" || ((Object)((Component)val3).gameObject).name.Contains("Cube.001")))
				{
					Plugin.Log.LogDebug((object)("Skipping securityCameraScreen.mesh (" + ((Object)val3).name + "): Cube.001 reserved for OBC."));
				}
				else
				{
					Plugin.Log.LogDebug((object)"securityCameraScreen not reused (whitelist: SingleScreen + insideCameraScreen only).");
				}
			}
			return result;
			void TryAdd(MeshRenderer? mr, string label)
			{
				if (!((Object)(object)mr == (Object)null))
				{
					int instanceID = ((Object)mr).GetInstanceID();
					if (!claimed.Contains(instanceID))
					{
						if (!IsWhitelistedScreen(mr, out string rejectReason))
						{
							Plugin.Log.LogDebug((object)("Skipping " + label + " (" + ((Object)mr).name + "): " + rejectReason));
						}
						else
						{
							claimed.Add(instanceID);
							result.Add(mr);
							Plugin.Log.LogInfo((object)("Reusable screen (whitelist): " + label + " -> " + GetPath(((Component)mr).transform)));
						}
					}
				}
			}
		}

		private static bool IsWhitelistedScreen(MeshRenderer mr, out string rejectReason)
		{
			rejectReason = "ok";
			if (BodyCamComponent.AnyBodyCamHasReference((Renderer)(object)mr))
			{
				rejectReason = "already owned by OpenBodyCams body cam";
				return false;
			}
			if (((Object)((Component)mr).gameObject).name == "Cube.001" || ((Object)((Component)mr).gameObject).name.Contains("Cube.001"))
			{
				rejectReason = "Cube.001 reserved for OBC main panel";
				return false;
			}
			ManualCameraRenderer val = StartOfRound.Instance?.mapScreen;
			if ((Object)(object)val != (Object)null && (Object)(object)val.mesh == (Object)(object)mr)
			{
				rejectReason = "radar map screen";
				return false;
			}
			string name = ((Object)((Component)mr).gameObject).name;
			string[] rejectNameTokens = RejectNameTokens;
			foreach (string text in rejectNameTokens)
			{
				if (name.IndexOf(text, StringComparison.OrdinalIgnoreCase) >= 0)
				{
					rejectReason = "name contains '" + text + "'";
					return false;
				}
			}
			if (IsUnderCube001Buttons(((Component)mr).transform))
			{
				rejectReason = "child of Cube.001 button object";
				return false;
			}
			if (name.IndexOf("Overlay", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("BodyCamOverlay", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				rejectReason = "overlay mesh";
				return false;
			}
			return true;
		}

		private static bool IsUnderCube001Buttons(Transform? t)
		{
			while ((Object)(object)t != (Object)null)
			{
				string name = ((Object)t).name;
				if (name.IndexOf("CameraMonitorOn", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("CameraMonitorSwitch", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("OnButton", StringComparison.OrdinalIgnoreCase) >= 0 || (name.IndexOf("Button", StringComparison.OrdinalIgnoreCase) >= 0 && (Object)(object)t.parent != (Object)null && (((Object)t.parent).name == "Cube.001" || ((Object)t.parent).name.Contains("Cube.001"))))
				{
					return true;
				}
				if ((Object)(object)t.parent != (Object)null && (((Object)t.parent).name == "Cube.001" || ((Object)t.parent).name.Contains("Cube.001")) && (name.StartsWith("Cube (", StringComparison.Ordinal) || name.IndexOf("Button", StringComparison.OrdinalIgnoreCase) >= 0))
				{
					return true;
				}
				t = t.parent;
			}
			return false;
		}

		private void EnsureCloneTemplate(List<MeshRenderer> reusable)
		{
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: 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)
			GameObject val = GameObject.Find("Environment/HangarShip/ShipModels2b/MonitorWall/SingleScreen");
			if ((Object)(object)val != (Object)null)
			{
				MeshRenderer component = val.GetComponent<MeshRenderer>();
				if ((Object)(object)component != (Object)null)
				{
					_cloneTemplate = component;
					ManualLogSource log = Plugin.Log;
					string[] obj = new string[5]
					{
						"Clone template: SingleScreen (",
						GetPath(((Component)component).transform),
						") ",
						null,
						null
					};
					object arg = ((Component)component).transform.localPosition;
					Quaternion localRotation = ((Component)component).transform.localRotation;
					obj[3] = $"localPos={arg} localRot={((Quaternion)(ref localRotation)).eulerAngles} ";
					object arg2 = ((Component)component).transform.localScale;
					Material[] sharedMaterials = ((Renderer)component).sharedMaterials;
					obj[4] = $"localScale={arg2} mats={((sharedMaterials != null) ? sharedMaterials.Length : 0)}";
					log.LogInfo((object)string.Concat(obj));
					return;
				}
			}
			foreach (MeshRenderer item in reusable)
			{
				if (!((Object)(object)item == (Object)null) && !(((Object)((Component)item).gameObject).name == "Cube.001") && !((Object)((Component)item).gameObject).name.Contains("Cube.001"))
				{
					_cloneTemplate = item;
					Plugin.Log.LogInfo((object)("Clone template: reusable " + ((Object)item).name + " (" + GetPath(((Component)item).transform) + ")"));
					return;
				}
			}
			if ((Object)(object)_monitorWall != (Object)null)
			{
				MeshRenderer[] componentsInChildren = ((Component)_monitorWall).GetComponentsInChildren<MeshRenderer>(true);
				foreach (MeshRenderer val2 in componentsInChildren)
				{
					if (!(((Object)((Component)val2).gameObject).name == "Cube.001") && !((Object)((Component)val2).gameObject).name.Contains("Cube.001") && IsWhitelistedScreen(val2, out string _))
					{
						_cloneTemplate = val2;
						Plugin.Log.LogInfo((object)("Clone template: MonitorWall screen " + ((Object)val2).name + " (" + GetPath(((Component)val2).transform) + ")"));
						return;
					}
				}
			}
			_cloneTemplate = CreateQuadTemplate();
			if ((Object)(object)_cloneTemplate != (Object)null)
			{
				Plugin.Log.LogInfo((object)("Clone template: fallback Quad (" + GetPath(((Component)_cloneTemplate).transform) + ")"));
			}
			else
			{
				Plugin.Log.LogWarning((object)"No clone template MeshRenderer found (SingleScreen/Quad unavailable).");
			}
		}

		private MeshRenderer? CreateQuadTemplate()
		{
			if ((Object)(object)_ownedQuadTemplate != (Object)null)
			{
				MeshRenderer component = _ownedQuadTemplate.GetComponent<MeshRenderer>();
				if ((Object)(object)component != (Object)null)
				{
					return component;
				}
			}
			GameObject val = GameObject.CreatePrimitive((PrimitiveType)5);
			((Object)val).name = "CrewMonitors_QuadTemplate";
			((Object)val).hideFlags = (HideFlags)61;
			val.SetActive(false);
			Collider[] components = val.GetComponents<Collider>();
			for (int i = 0; i < components.Length; i++)
			{
				Object.Destroy((Object)(object)components[i]);
			}
			if ((Object)(object)_monitorWall != (Object)null)
			{
				val.transform.SetParent(_monitorWall, false);
			}
			_ownedQuadTemplate = val;
			return val.GetComponent<MeshRenderer>();
		}

		private GameObject CloneMonitor(int slotIndex, out MeshRenderer? renderer)
		{
			//IL_016a: 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_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d3: 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_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0225: Unknown result type (might be due to invalid IL or missing references)
			//IL_022a: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ea: 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_0379: Unknown result type (might be due to invalid IL or missing references)
			//IL_038e: Unknown result type (might be due to invalid IL or missing references)
			//IL_041a: Unknown result type (might be due to invalid IL or missing references)
			//IL_042a: Unknown result type (might be due to invalid IL or missing references)
			//IL_042f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0433: Unknown result type (might be due to invalid IL or missing references)
			//IL_0450: Unknown result type (might be due to invalid IL or missing references)
			//IL_0460: Unknown result type (might be due to invalid IL or missing references)
			renderer = null;
			if ((Object)(object)_cloneTemplate == (Object)null || (Object)(object)_monitorWall == (Object)null)
			{
				return null;
			}
			Transform val = (((Object)(object)_placementAnchor != (Object)null) ? _placementAnchor : _monitorWall);
			GameObject val2 = Object.Instantiate<GameObject>(((Component)_cloneTemplate).gameObject, val);
			((Object)val2).name = string.Format("{0}{1}", "CrewMonitor_Clone_", slotIndex);
			((Object)val2).hideFlags = (HideFlags)0;
			val2.SetActive(true);
			BodyCamComponent[] componentsInChildren = val2.GetComponentsInChildren<BodyCamComponent>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren[i]);
			}
			SyncBodyCamToRadarMap[] componentsInChildren2 = val2.GetComponentsInChildren<SyncBodyCamToRadarMap>(true);
			for (int i = 0; i < componentsInChildren2.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren2[i]);
			}
			ManualCameraRenderer[] componentsInChildren3 = val2.GetComponentsInChildren<ManualCameraRenderer>(true);
			for (int i = 0; i < componentsInChildren3.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren3[i]);
			}
			Collider[] componentsInChildren4 = val2.GetComponentsInChildren<Collider>(true);
			for (int i = 0; i < componentsInChildren4.Length; i++)
			{
				componentsInChildren4[i].enabled = false;
			}
			float value = Plugin.CloneSpacing.Value;
			float num = Mathf.Clamp(Plugin.CloneScaleFactor.Value, 0.1f, 1f);
			int num2 = Mathf.Clamp(Plugin.GridColumns.Value, 1, 8);
			int num3 = slotIndex % num2;
			int num4 = slotIndex / num2;
			float num5 = num * 3.3333333f;
			Vector3 localScale = ((Component)_cloneTemplate).transform.localScale * num5;
			val2.transform.localScale = localScale;
			Vector3 center = default(Vector3);
			if (_wallPlacementValid)
			{
				WallPlacement wallPlacement = _wallPlacement;
				float value2 = Plugin.GridHorizontalOffset.Value;
				float value3 = Plugin.GridVerticalOffset.Value;
				float num6 = value2 + ((float)num3 - (float)(num2 - 1) * 0.5f) * value;
				float num7 = value3 + (float)num4 * value * 0.85f;
				center = ((Bounds)(ref wallPlacement.LocalBounds)).center;
				int horizontalAxis = wallPlacement.HorizontalAxis;
				Vector3 center2 = ((Bounds)(ref wallPlacement.LocalBounds)).center;
				((Vector3)(ref center))[horizontalAxis] = ((Vector3)(ref center2))[wallPlacement.HorizontalAxis] + wallPlacement.HSign * num6;
				int verticalAxis = wallPlacement.VerticalAxis;
				center2 = ((Bounds)(ref wallPlacement.LocalBounds)).center;
				((Vector3)(ref center))[verticalAxis] = ((Vector3)(ref center2))[wallPlacement.VerticalAxis] + wallPlacement.VSign * num7;
				((Vector3)(ref center))[wallPlacement.DepthAxis] = wallPlacement.FlushDepth;
			}
			else
			{
				float value4 = Plugin.GridHorizontalOffset.Value;
				float value5 = Plugin.GridVerticalOffset.Value;
				int num8 = Mathf.Clamp(Plugin.GridColumns.Value, 1, 8);
				((Vector3)(ref center))..ctor(value4 + ((float)num3 - (float)(num8 - 1) * 0.5f) * value, value5 + (float)num4 * value * 0.85f, 0f - Plugin.WallInset.Value);
				Plugin.Log.LogWarning((object)$"Clone {slotIndex}: wall placement bounds unavailable; using fallback localPos={center}");
			}
			val2.transform.localPosition = center;
			val2.transform.localRotation = Quaternion.Euler(0f, 0f, Plugin.GridYawDegrees.Value);
			renderer = val2.GetComponent<MeshRenderer>();
			if ((Object)(object)renderer == (Object)null)
			{
				renderer = val2.GetComponentInChildren<MeshRenderer>();
			}
			string text = (_wallPlacementValid ? ($"depthAxis={AxisNames[_wallPlacement.DepthAxis]} flushDepth={_wallPlacement.FlushDepth} " + $"boundsCenter={((Bounds)(ref _wallPlacement.LocalBounds)).center} boundsSize={((Bounds)(ref _wallPlacement.LocalBounds)).size} " + $"maxIsOutward={_wallPlacement.MaxIsOutward}") : "depthAxis=n/a");
			ManualLogSource log = Plugin.Log;
			string[] obj = new string[7]
			{
				$"Cloned monitor slot {slotIndex}: template={((Object)((Component)_cloneTemplate).gameObject).name} ",
				$"parent={((Object)val).name} col={num3} row={num4} ",
				null,
				null,
				null,
				null,
				null
			};
			object arg = val2.transform.localPosition;
			Quaternion localRotation = val2.transform.localRotation;
			obj[2] = $"localPos={arg} localRot={((Quaternion)(ref localRotation)).eulerAngles} ";
			obj[3] = $"localScale={val2.transform.localScale} worldPos={val2.transform.position} ";
			obj[4] = $"inset={Plugin.WallInset.Value} scaleFactor={num} panelMul={num5} ";
			obj[5] = $"spacing={value} xBase={Plugin.GridHorizontalOffset.Value} yBase={Plugin.GridVerticalOffset.Value} yaw={Plugin.GridYawDegrees.Value} ";
			obj[6] = text;
			log.LogInfo((object)string.Concat(obj));
			return val2;
		}

		private static void IsolateScreenMaterial(MeshRenderer renderer, int matIndex)
		{
			//IL_002f: 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_004d: Expected O, but got Unknown
			Material[] sharedMaterials = ((Renderer)renderer).sharedMaterials;
			if (sharedMaterials != null && matIndex >= 0 && matIndex < sharedMaterials.Length && !((Object)(object)sharedMaterials[matIndex] == (Object)null))
			{
				sharedMaterials = (Material[])sharedMaterials.Clone();
				Material val = new Material(sharedMaterials[matIndex])
				{
					name = ((Object)sharedMaterials[matIndex]).name + " (CrewSlot)"
				};
				sharedMaterials[matIndex] = val;
				((Renderer)renderer).sharedMaterials = sharedMaterials;
			}
		}

		private static int PickMaterialIndex(MeshRenderer renderer)
		{
			Material[] sharedMaterials = ((Renderer)renderer).sharedMaterials;
			if (sharedMaterials == null || sharedMaterials.Length == 0)
			{
				return 0;
			}
			string name = ((Object)((Component)renderer).gameObject).name;
			bool flag = name == "Cube.001" || name.Contains("Cube.001");
			int num = ((flag && sharedMaterials.Length > 2) ? 2 : ((sharedMaterials.Length > 1) ? 1 : 0));
			Plugin.Log.LogInfo((object)$"PickMaterialIndex({name}): index={num} (mats={sharedMaterials.Length}, isCube001={flag})");
			return num;
		}

		private TextMeshPro? CreateNameplate(GameObject host, MeshRenderer renderer)
		{
			//IL_0005: 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_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: 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_004c: 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_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: 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_00dd: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				GameObject val = new GameObject("CrewMonitor_Nameplate");
				val.transform.SetParent(host.transform, false);
				Bounds localBounds = ((Renderer)renderer).localBounds;
				val.transform.localPosition = new Vector3(0f, ((Bounds)(ref localBounds)).min.y - 0.05f, ((Bounds)(ref localBounds)).center.z);
				val.transform.localRotation = Quaternion.identity;
				val.transform.localScale = Vector3.one * 0.02f;
				TextMeshPro val2 = val.AddComponent<TextMeshPro>();
				((TMP_Text)val2).text = "";
				((TMP_Text)val2).alignment = (TextAlignmentOptions)514;
				((TMP_Text)val2).fontSize = 36f;
				((Graphic)val2).color = new Color(1f, 0.55f, 0.15f, 1f);
				((TMP_Text)val2).enableAutoSizing = false;
				((TMP_Text)val2).rectTransform.sizeDelta = new Vector2(20f, 4f);
				StartOfRound instance = StartOfRound.Instance;
				object obj;
				if (instance == null)
				{
					obj = null;
				}
				else
				{
					TextMeshProUGUI mapScreenPlayerName = instance.mapScreenPlayerName;
					obj = ((mapScreenPlayerName != null) ? ((TMP_Text)mapScreenPlayerName).font : null);
				}
				TMP_FontAsset val3 = (TMP_FontAsset)obj;
				if ((Object)(object)val3 != (Object)null)
				{
					((TMP_Text)val2).font = val3;
				}
				return val2;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Nameplate create failed: " + ex.Message));
				return null;
			}
		}

		private void RefreshAssignments()
		{
			if (!_setupComplete || _slots.Count == 0)
			{
				return;
			}
			List<PlayerControllerB> livingPlayers = GetLivingPlayers();
			bool value = Plugin.AlwaysShowMonitors.Value;
			int num = Mathf.Min(livingPlayers.Count, _slots.Count);
			for (int i = 0; i < _slots.Count; i++)
			{
				CrewSlot crewSlot = _slots[i];
				if ((Object)(object)crewSlot.BodyCam == (Object)null)
				{
					continue;
				}
				if (crewSlot.UserCycled)
				{
					if (crewSlot.CycleIndex <= -2)
					{
						ApplyManualOff(crewSlot, value);
						UpdateInteractionTips(crewSlot);
						continue;
					}
					if (crewSlot.CycleIndex == -1)
					{
						ApplyExternalCam(crewSlot, value);
						UpdateInteractionTips(crewSlot);
						continue;
					}
					PlayerControllerB val = null;
					if ((Object)(object)crewSlot.AssignedPlayer != (Object)null && IsLivingPlayer(crewSlot.AssignedPlayer))
					{
						val = crewSlot.AssignedPlayer;
					}
					else if (crewSlot.CycleIndex >= 0 && crewSlot.CycleIndex < livingPlayers.Count)
					{
						val = livingPlayers[crewSlot.CycleIndex];
					}
					if ((Object)(object)val != (Object)null)
					{
						int num2 = livingPlayers.IndexOf(val);
						if (num2 >= 0)
						{
							crewSlot.CycleIndex = num2;
						}
						if (crewSlot.ShowMapFeed)
						{
							ApplyMapFeed(crewSlot, val, value);
						}
						else
						{
							ApplySlotAssignment(crewSlot, val, value, $"Slot {i + 1}");
						}
					}
					else
					{
						crewSlot.CycleIndex = -2;
						crewSlot.ShowMapFeed = false;
						ApplyManualOff(crewSlot, value);
					}
					UpdateInteractionTips(crewSlot);
				}
				else
				{
					if (i < num)
					{
						crewSlot.CycleIndex = i;
						crewSlot.ShowMapFeed = false;
						ApplySlotAssignment(crewSlot, livingPlayers[i], value, $"Slot {i + 1}");
					}
					else
					{
						crewSlot.CycleIndex = -2;
						crewSlot.ShowMapFeed = false;
						ApplyManualOff(crewSlot, value);
					}
					UpdateInteractionTips(crewSlot);
				}
			}
		}

		private static void ApplyManualOff(CrewSlot slot, bool alwaysShow)
		{
			slot.AssignedPlayer = null;
			slot.ShowMapFeed = false;
			StopMapFeedCamera(slot);
			slot.BodyCam.SetTargetToNone();
			SetMonitorOffMaterial(slot.BodyCam, GetBlackScreenMaterial());
			if (slot.BodyCam.IsScreenPowered())
			{
				slot.BodyCam.SetScreenPowered(false);
			}
			else
			{
				slot.BodyCam.UpdateScreenMaterial();
			}
			if (slot.IsClone && (Object)(object)slot.Host != (Object)null)
			{
				if (alwaysShow && !slot.Host.activeSelf)
				{
					slot.Host.SetActive(true);
				}
				else if (!alwaysShow && slot.Host.activeSelf)
				{
					slot.Host.SetActive(false);
				}
			}
			if ((Object)(object)slot.Nameplate != (Object)null)
			{
				if (alwaysShow)
				{
					((TMP_Text)slot.Nameplate).text = "Off";
					((Component)slot.Nameplate).gameObject.SetActive(true);
				}
				else
				{
					((TMP_Text)slot.Nameplate).text = "";
					((Component)slot.Nameplate).gameObject.SetActive(false);
				}
			}
		}

		private static void ApplyExternalCam(CrewSlot slot, bool alwaysShow)
		{
			slot.AssignedPlayer = null;
			slot.ShowMapFeed = false;
			StopMapFeedCamera(slot);
			slot.BodyCam.SetTargetToNone();
			if ((Object)(object)slot.OriginalOffMaterial != (Object)null)
			{
				SetMonitorOffMaterial(slot.BodyCam, slot.OriginalOffMaterial);
			}
			if (slot.BodyCam.IsScreenPowered())
			{
				slot.BodyCam.SetScreenPowered(false);
			}
			else
			{
				slot.BodyCam.UpdateScreenMaterial();
			}
			if (slot.IsClone && (Object)(object)slot.Host != (Object)null)
			{
				if (alwaysShow && !slot.Host.activeSelf)
				{
					slot.Host.SetActive(true);
				}
				else if (!alwaysShow && slot.Host.activeSelf)
				{
					slot.Host.SetActive(false);
				}
			}
			if ((Object)(object)slot.Nameplate != (Object)null)
			{
				if (alwaysShow)
				{
					((TMP_Text)slot.Nameplate).text = "External";
					((Component)slot.Nameplate).gameObject.SetActive(true);
				}
				else
				{
					((TMP_Text)slot.Nameplate).text = "";
					((Component)slot.Nameplate).gameObject.SetActive(false);
				}
			}
		}

		private void ApplyMapFeed(CrewSlot slot, PlayerControllerB player, bool alwaysShow)
		{
			slot.AssignedPlayer = player;
			slot.ShowMapFeed = true;
			slot.BodyCam.SetTargetToNone();
			if (slot.IsClone && (Object)(object)slot.Host != (Object)null)
			{
				if (alwaysShow && !slot.Host.activeSelf)
				{
					slot.Host.SetActive(true);
				}
				else if (!alwaysShow && slot.Host.activeSelf)
				{
					slot.Host.SetActive(false);
				}
			}
			slot.BodyCam.SetScreenPowered(true);
			ApplyScreenBrightness(slot.BodyCam);
			EnsureMapFeedCamera(slot);
			UpdateMapFeedFollow(slot);
			ApplyMapFeedTextureToMonitor(slot);
			if ((Object)(object)slot.Nameplate != (Object)null)
			{
				string text = (string.IsNullOrEmpty(player.playerUsername) ? $"Player {player.playerClientId}" : player.playerUsername);
				((TMP_Text)slot.Nameplate).text = text + " Map";
				((Component)slot.Nameplate).gameObject.SetActive(true);
			}
		}

		private void EnsureMapFeedCamera(CrewSlot slot)
		{
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Expected O, but got Unknown
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: 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_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			Camera val = (StartOfRound.Instance?.mapScreen)?.mapCamera;
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogWarning((object)$"Slot {slot.Index}: mapCamera unavailable for map feed.");
				return;
			}
			if ((Object)(object)slot.MapFeedCamera != (Object)null && (Object)(object)slot.MapFeedTexture != (Object)null)
			{
				if (!((Component)slot.MapFeedCamera).gameObject.activeSelf)
				{
					((Component)slot.MapFeedCamera).gameObject.SetActive(true);
				}
				((Behaviour)slot.MapFeedCamera).enabled = true;
				return;
			}
			DestroyMapFeedResources(slot);
			Transform val2 = (((Object)(object)_slotRoot != (Object)null) ? _slotRoot.transform : ((Component)this).transform);
			GameObject val3 = new GameObject($"CrewMapFeedCam_{slot.Index}");
			val3.transform.SetParent(val2, false);
			val3.transform.SetPositionAndRotation(((Component)val).transform.position, ((Component)val).transform.rotation);
			val3.transform.localScale = Vector3.one;
			Camera val4 = val3.AddComponent<Camera>();
			CopyMapCameraSettings(val4, val);
			int num = 480;
			int num2 = 360;
			try
			{
				BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
				object? obj = typeof(BodyCamComponent).GetField("Camera", bindingAttr)?.GetValue(slot.BodyCam);
				Camera val5 = (Camera)((obj is Camera) ? obj : null);
				if ((Object)(object)((val5 != null) ? val5.targetTexture : null) != (Object)null)
				{
					num = Mathf.Max(16, ((Texture)val5.targetTexture).width);
					num2 = Mathf.Max(16, ((Texture)val5.targetTexture).height);
				}
			}
			catch
			{
			}
			RenderTexture val6 = new RenderTexture(num, num2, 24)
			{
				name = $"CrewMapFeedRT_{slot.Index}",
				filterMode = (FilterMode)1,
				antiAliasing = 1
			};
			val6.Create();
			val4.targetTexture = val6;
			((Behaviour)val4).enabled = true;
			TryConfigureHdrpMapCamera(val4, val);
			slot.MapFeedCamera = val4;
			slot.MapFeedTexture = val6;
			Plugin.Log.LogInfo((object)$"Slot {slot.Index}: dedicated map feed camera ready ({num}x{num2}).");
		}

		private static void CopyMapCameraSettings(Camera dest, Camera src)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			dest.orthographic = src.orthographic;
			dest.orthographicSize = src.orthographicSize;
			dest.fieldOfView = src.fieldOfView;
			dest.nearClipPlane = src.nearClipPlane;
			dest.farClipPlane = src.farClipPlane;
			dest.cullingMask = src.cullingMask;
			dest.clearFlags = src.clearFlags;
			dest.backgroundColor = src.backgroundColor;
			dest.depth = src.depth - 1f;
			dest.allowHDR = src.allowHDR;
			dest.allowMSAA = src.allowMSAA;
			dest.useOcclusionCulling = src.useOcclusionCulling;
			dest.renderingPath = src.renderingPath;
			dest.aspect = src.aspect;
		}

		private static void TryConfigureHdrpMapCamera(Camera dest, Camera src)
		{
			try
			{
				Component component = ((Component)src).GetComponent("HDAdditionalCameraData");
				if ((Object)(object)component == (Object)null)
				{
					return;
				}
				Type type = ((object)component).GetType();
				Component obj = ((Component)dest).GetComponent(type) ?? ((Component)dest).gameObject.AddComponent(type);
				string[] array = new string[6] { "volumeLayerMask", "probeLayerMask", "clearColorMode", "backgroundColorHDR", "customRenderingSettings", "volumeAnchorOverride" };
				foreach (string name in array)
				{
					FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (!(field == null) && !field.IsInitOnly && !field.IsLiteral)
					{
						try
						{
							field.SetValue(obj, field.GetValue(component));
						}
						catch
						{
						}
					}
				}
				type.GetField("hasPersistentHistory", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.SetValue(obj, true);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogDebug((object)("HDRP map cam configure skipped: " + ex.Message));
			}
		}

		private void UpdateMapFeedFollow(CrewSlot slot)
		{
			//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_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: 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_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: 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_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_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			Camera mapFeedCamera = slot.MapFeedCamera;
			PlayerControllerB assignedPlayer = slot.AssignedPlayer;
			if ((Object)(object)mapFeedCamera == (Object)null || (Object)(object)assignedPlayer == (Object)null)
			{
				return;
			}
			Vector3 val;
			if (assignedPlayer.isPlayerDead)
			{
				val = (((Object)(object)assignedPlayer.redirectToEnemy != (Object)null) ? ((Component)assignedPlayer.redirectToEnemy).transform.position : ((!((Object)(object)assignedPlayer.deadBody != (Object)null) || !((Component)assignedPlayer.deadBody).gameObject.activeSelf) ? assignedPlayer.placeOfDeath : ((Component)assignedPlayer.deadBody).transform.position));
			}
			else
			{
				val = ((Component)assignedPlayer).transform.position;
				int num = (((Object)(object)StartOfRound.Instance != (Object)null) ? StartOfRound.Instance.collidersAndRoomMask : (-5));
				RaycastHit val2 = default(RaycastHit);
				if (Physics.Raycast(((Component)assignedPlayer).transform.position + Vector3.up * 0.1f, Vector3.down, ref val2, 5f, num, (QueryTriggerInteraction)1))
				{
					val = ((RaycastHit)(ref val2)).point + Vector3.up * 0.06f;
				}
			}
			ManualCameraRenderer val3 = StartOfRound.Instance?.mapScreen;
			float num2 = (((Object)(object)val3 != (Object)null) ? val3.cameraNearPlane : (-2.47f));
			float num3 = (((Object)(object)val3 != (Object)null) ? val3.cameraFarPlane : 7.52f);
			if (assignedPlayer.isInHangarShipRoom)
			{
				mapFeedCamera.nearClipPlane = -0.96f;
				mapFeedCamera.farClipPlane = 7.52f;
			}
			else if (!assignedPlayer.isInsideFactory)
			{
				mapFeedCamera.nearClipPlane = num2 - 18f;
				mapFeedCamera.farClipPlane = num3 + 18f;
			}
			else
			{
				mapFeedCamera.nearClipPlane = num2;
				mapFeedCamera.farClipPlane = num3;
			}
			((Component)mapFeedCamera).transform.position = new Vector3(val.x, val.y + 3.636f, val.z);
			Camera val4 = val3?.mapCamera;
			if ((Object)(object)val4 != (Object)null)
			{
				((Component)mapFeedCamera).transform.rotation = ((Component)val4).transform.rotation;
			}
		}

		private void ApplyMapFeedTextureToMonitor(CrewSlot slot)
		{
			if ((Object)(object)slot.MapFeedTexture == (Object)null || (Object)(object)slot.BodyCam == (Object)null)
			{
				return;
			}
			try
			{
				Material monitorOnMaterial = GetMonitorOnMaterial(slot.BodyCam);
				if (!((Object)(object)monitorOnMaterial == (Object)null))
				{
					monitorOnMaterial = UnshareMonitorOnMaterial(slot, monitorOnMaterial);
					monitorOnMaterial.mainTexture = (Texture)(object)slot.MapFeedTexture;
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("ApplyMapFeedTextureToMonitor failed: " + ex.Message));
			}
		}

		private static void StopMapFeedCamera(CrewSlot slot)
		{
			if (!((Object)(object)slot.MapFeedCamera == (Object)null))
			{
				((Behaviour)slot.MapFeedCamera).enabled = false;
				if (((Component)slot.MapFeedCamera).gameObject.activeSelf)
				{
					((Component)slot.MapFeedCamera).gameObject.SetActive(false);
				}
			}
		}

		private static void DestroyMapFeedResources(CrewSlot slot)
		{
			if ((Object)(object)slot.MapFeedCamera != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)slot.MapFeedCamera).gameObject);
				slot.MapFeedCamera = null;
			}
			if ((Object)(object)slot.MapFeedTexture != (Object)null)
			{
				if (slot.MapFeedTexture.IsCreated())
				{
					slot.MapFeedTexture.Release();
				}
				Object.Destroy((Object)(object)slot.MapFeedTexture);
				slot.MapFeedTexture = null;
			}
		}

		private static Material? GetMonitorOnMaterial(BodyCamComponent bodyCam)
		{
			BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
			object? obj = typeof(BodyCamComponent).GetField("MonitorOnMaterial", bindingAttr)?.GetValue(bodyCam);
			return (Material?)((obj is Material) ? obj : null);
		}

		private Material UnshareMonitorOnMaterial(CrewSlot slot, Material mat)
		{
			//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_0087: Expected O, but got Unknown
			bool flag = false;
			foreach (CrewSlot slot2 in _slots)
			{
				if (slot2 != slot && !((Object)(object)slot2.BodyCam == (Object)null) && (Object)(object)GetMonitorOnMaterial(slot2.BodyCam) == (Object)(object)mat)
				{
					flag = true;
					break;
				}
			}
			if (!flag)
			{
				return mat;
			}
			Material val = new Material(mat)
			{
				name = ((Object)mat).name + " Slot" + slot.Index
			};
			typeof(BodyCamComponent).GetField("MonitorOnMaterial", BodyCamFlags)?.SetValue(slot.BodyCam, val);
			try
			{
				slot.BodyCam.UpdateScreenMaterial();
			}
			catch
			{
			}
			return val;
		}

		private static void RestoreBodyCamTexture(BodyCamComponent bodyCam)
		{
			if ((Object)(object)bodyCam == (Object)null)
			{
				return;
			}
			try
			{
				BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
				object? obj = typeof(BodyCamComponent).GetField("Camera", bindingAttr)?.GetValue(bodyCam);
				Camera val = (Camera)((obj is Camera) ? obj : null);
				Material monitorOnMaterial = GetMonitorOnMaterial(bodyCam);
				if (!((Object)(object)monitorOnMaterial == (Object)null))
				{
					if ((Object)(object)val != (Object)null && (Object)(object)val.targetTexture != (Object)null)
					{
						monitorOnMaterial.mainTexture = (Texture)(object)val.targetTexture;
					}
					try
					{
						bodyCam.UpdateScreenMaterial();
					}
					catch
					{
					}
					if ((Object)(object)val != (Object)null && (Object)(object)val.targetTexture != (Object)null)
					{
						monitorOnMaterial.mainTexture = (Texture)(object)val.targetTexture;
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("RestoreBodyCamTexture failed: " + ex.Message));
			}
		}

		private void ApplySlotAssignment(CrewSlot slot, PlayerControllerB? player, bool alwaysShow, string blankLabel)
		{
			if ((Object)(object)player != (Object)null)
			{
				bool showMapFeed = slot.ShowMapFeed;
				slot.ShowMapFeed = false;
				if (showMapFeed)
				{
					StopMapFeedCamera(slot);
				}
				slot.BodyCam.SetTargetToPlayer(player);
				slot.AssignedPlayer = player;
				slot.BodyCam.SetScreenPowered(true);
				ApplyScreenBrightness(slot.BodyCam);
				RestoreBodyCamTexture(slot.BodyCam);
				if (showMapFeed)
				{
					Plugin.Log.LogInfo((object)"Slot restored body-cam RT after map feed.");
				}
				if (slot.IsClone && (Object)(object)slot.Host != (Object)null && !slot.Host.activeSelf)
				{
					slot.Host.SetActive(true);
				}
				UpdateNameplate(slot, player);
			}
			else if (alwaysShow)
			{
				slot.AssignedPlayer = null;
				slot.BodyCam.SetTargetToNone();
				slot.BodyCam.SetScreenPowered(true);
				ApplyScreenBrightness(slot.BodyCam);
				if (slot.IsClone && (Object)(object)slot.Host != (Object)null && !slot.Host.activeSelf)
				{
					slot.Host.SetActive(true);
				}
				if ((Object)(object)slot.Nameplate != (Object)null)
				{
					((TMP_Text)slot.Nameplate).text = blankLabel;
					((Component)slot.Nameplate).gameObject.SetActive(true);
				}
			}
			else
			{
				slot.AssignedPlayer = null;
				slot.BodyCam.SetTargetToNone();
				slot.BodyCam.SetScreenPowered(false);
				if (slot.IsClone && (Object)(object)slot.Host != (Object)null && slot.Host.activeSelf)
				{
					slot.Host.SetActive(false);
				}
				if ((Object)(object)slot.Nameplate != (Object)null)
				{
					((TMP_Text)slot.Nameplate).text = "";
					((Component)slot.Nameplate).gameObject.SetActive(false);
				}
			}
		}

		private static void UpdateNameplate(CrewSlot slot, PlayerControllerB player)
		{
			if (!((Object)(object)slot.Nameplate == (Object)null))
			{
				((Component)slot.Nameplate).gameObject.SetActive(true);
				((TMP_Text)slot.Nameplate).text = (string.IsNullOrEmpty(player.playerUsername) ? $"Player {player.playerClientId}" : player.playerUsername);
			}
		}

		private static bool IsLivingPlayer(PlayerControllerB p)
		{
			if ((Object)(object)p != (Object)null && p.isPlayerControlled)
			{
				return !p.isPlayerDead;
			}
			return false;
		}

		private static List<PlayerControllerB> GetLivingPlayers()
		{
			StartOfRound instance = StartOfRound.Instance;
			if ((Object)(object)instance == (Object)null || instance.allPlayerScripts == null)
			{
				return new List<PlayerControllerB>();
			}
			IEnumerable<PlayerControllerB> source = instance.allPlayerScripts.Where((PlayerControllerB p) => (Object)(object)p != (Object)null && p.isPlayerControlled && !p.isPlayerDead);
			if (!Plugin.IncludeLocalPlayer.Value)
			{
				PlayerControllerB local = GameNetworkManager.Instance?.localPlayerController;
				if ((Object)(object)local != (Object)null)
				{
					source = source.Where((PlayerControllerB p) => (Object)(object)p != (Object)(object)local);
				}
			}
			return source.OrderBy((PlayerControllerB p) => p.playerClientId).ToList();
		}

		private void SetupSlotInteractions(CrewSlot slot)
		{
			if ((Object)(object)slot.Host == (Object)null || (Object)(object)slot.Renderer == (Object)null)
			{
				return;
			}
			try
			{
				slot.FocusTrigger = CreateFocusTrigger(slot);
				slot.CycleButton = CreateCycleButton(slot);
				UpdateInteractionTips(slot);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)$"Slot {slot.Index} interaction setup failed: {ex.Message}");
			}
		}

		private GameObject CreateFocusTrigger(CrewSlot slot)
		{
			//IL_0005: 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_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: 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_00a2: 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_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: 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_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			//IL_021a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0225: Expected O, but got Unknown
			//IL_023f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0270: Expected O, but got Unknown
			GameObject val = new GameObject("CrewMonitor_FocusTrigger");
			val.transform.SetParent(slot.Host.transform, false);
			val.tag = "InteractTrigger";
			GameObject val2 = FindVanillaSwitchButton();
			int num = val.layer;
			if ((Object)(object)val2 != (Object)null)
			{
				InteractTrigger componentInChildren = val2.GetComponentInChildren<InteractTrigger>(true);
				num = (((Object)(object)componentInChildren != (Object)null) ? ((Component)componentInChildren).gameObject.layer : val2.layer);
			}
			if (num <= 0 || num == 8 || num == 30)
			{
				int num2 = LayerMask.NameToLayer("InteractableObject");
				num = ((num2 >= 0) ? num2 : 9);
			}
			val.layer = num;
			Bounds localBounds = ((Renderer)slot.Renderer).localBounds;
			GetScreenFaceAxes(localBounds, ((Component)slot.Renderer).transform, out var horiz, out var vert, out var depth);
			float outwardLocalOnAxis = GetOutwardLocalOnAxis(slot.Renderer, depth);
			float num3 = AxisComponent(((Bounds)(ref localBounds)).center, depth);
			float num4 = Mathf.Sign(outwardLocalOnAxis - num3);
			if (num4 == 0f)
			{
				num4 = 1f;
			}
			float num5 = outwardLocalOnAxis + num4 * 0.04f;
			Vector3 v = ((Bounds)(ref localBounds)).center;
			SetAxisComponent(ref v, depth, (AxisComponent(((Bounds)(ref localBounds)).center, depth) + num5) * 0.5f);
			SetAxisComponent(ref v, horiz, AxisComponent(((Bounds)(ref localBounds)).center, horiz) - AxisComponent(((Bounds)(ref localBounds)).extents, horiz) * 0.08f);
			SetAxisComponent(ref v, vert, AxisComponent(((Bounds)(ref localBounds)).center, vert) + AxisComponent(((Bounds)(ref localBounds)).extents, vert) * 0.06f);
			BoxCollider obj = val.AddComponent<BoxCollider>();
			obj.center = v;
			Vector3 v2 = ((Bounds)(ref localBounds)).size;
			SetAxisComponent(ref v2, horiz, Mathf.Max(0.05f, AxisComponent(((Bounds)(ref localBounds)).size, horiz) * 0.72f));
			SetAxisComponent(ref v2, vert, Mathf.Max(0.05f, AxisComponent(((Bounds)(ref localBounds)).size, vert) * 0.68f));
			SetAxisComponent(ref v2, depth, Mathf.Max(0.02f, Mathf.Abs(num5 - AxisComponent(((Bounds)(ref localBounds)).center, depth)) * 0.7f));
			obj.size = v2;
			((Collider)obj).isTrigger = false;
			InteractTrigger val3 = ConfigureInteractTrigger(val, "Focus");
			val3.hoverIcon = GetTransparentHoverIcon();
			val3.disabledHoverIcon = GetTransparentHoverIcon();
			CrewSlotInteractBridge crewSlotInteractBridge = val.AddComponent<CrewSlotInteractBridge>();
			crewSlotInteractBridge.Init(this, slot.Index, isCycleButton: false);
			((UnityEvent<PlayerControllerB>)(object)val3.onInteract).AddListener((UnityAction<PlayerControllerB>)crewSlotInteractBridge.OnInteract);
			return val;
		}

		private static void ApplyScreenBrightness(BodyCamComponent bodyCam)
		{
			//IL_005b: 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)
			if ((Object)(object)bodyCam == (Object)null)
			{
				return;
			}
			float num = Mathf.Clamp(Plugin.ScreenBrightness.Value, 0f, 1f);
			BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
			Type typeFromHandle = typeof(BodyCamComponent);
			try
			{
				object? obj = typeFromHandle.GetField("MonitorOnMaterial", bindingAttr)?.GetValue(bodyCam);
				Material val = (Material)((obj is Material) ? obj : null);
				if ((Object)(object)val != (Object)null)
				{
					val.color = Color.white;
					if (val.HasProperty("_EmissiveColor"))
					{
						val.SetColor("_EmissiveColor", GetBodyCamEmissiveColor());
					}
					if (val.HasProperty("_AlbedoAffectEmissive"))
					{
						val.SetFloat("_AlbedoAffectEmissive", 1f);
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Screen material emissive tune failed: " + ex.Message));
			}
			try
			{
				object? obj2 = typeFromHandle.GetField("nightVisionLight", bindingAttr)?.GetValue(bodyCam);
				Light val2 = (Light)((obj2 is Light) ? obj2 : null);
				if ((Object)(object)val2 != (Object)null)
				{
					val2.intensity = 367f * num;
					val2.range = 12f * num;
					((Behaviour)val2).enabled = num > 0.001f;
				}
			}
			catch (Exception ex2)
			{
				Plugin.Log.LogWarning((object)("ScreenBrightness nightVision tune failed: " + ex2.Message));
			}
		}

		private static Color GetBodyCamEmissiveColor()
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: 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)
			try
			{
				MethodInfo methodInfo = typeof(BodyCamComponent).Assembly.GetType("OpenBodyCams.Plugin")?.GetMethod("GetBodyCamEmissiveColor", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				if (methodInfo != null)
				{
					object obj = methodInfo.Invoke(null, null);
					if (obj is Color)
					{
						return (Color)obj;
					}
				}
			}
			catch
			{
			}
			return new Color(0.05f, 0.13f, 0.05f, 0f);
		}

		private GameObject CreateCycleButton(CrewSlot slot)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: 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_0068: 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_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: 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_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_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Expected O, but got Unknown
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: 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_01a6: 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_01de: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_027c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0288: Unknown result type (might be due to invalid IL or missing references)
			//IL_028a: Unknown result type (might be due to invalid IL or missing references)
			//IL_028f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0294: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02de: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0302: Unknown result type (might be due to invalid IL or missing references)
			//IL_0374: Unknown result type (might be due to invalid IL or missing references)
			//IL_0381: Unknown result type (might be due to invalid IL or missing references)
			//IL_0392: Unknown result type (might be due to invalid IL or missing references)
			//IL_0397: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0403: Unknown result type (might be due to invalid IL or missing references)
			//IL_0408: Unknown result type (might be due to invalid IL or missing references)
			//IL_041b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0421: Unknown result type (might be due to invalid IL or missing references)
			//IL_042b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0431: Unknown result type (might be due to invalid IL or missing references)
			//IL_043b: 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_044b: 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_0462: Unknown result type (might be due to invalid IL or missing references)
			//IL_046d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0487: Unknown result type (might be due to invalid IL or missing references)
			//IL_0491: Unknown result type (might be due to invalid IL or missing references)
			//IL_049c: Expected O, but got Unknown
			//IL_049e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0540: Unknown result type (might be due to invalid IL or missing references)
			//IL_0551: Unknown result type (might be due to invalid IL or missing references)
			//IL_0568: Unknown result type (might be due to invalid IL or missing references)
			MeshRenderer renderer = slot.Renderer;
			Bounds localBounds = ((Renderer)renderer).localBounds;
			GetScreenFaceAxes(localBounds, ((Component)renderer).transform, out var horiz, out var vert, out var depth);
			float num = AxisComponent(((Bounds)(ref localBounds)).size, horiz);
			float num2 = AxisComponent(((Bounds)(ref localBounds)).size, vert);
			float num3 = Mathf.Clamp(Mathf.Min(num, num2) * 0.15f, 0.06f, 0.22f);
			Vector3 v = ((Bounds)(ref localBounds)).center;
			SetAxisComponent(ref v, horiz, AxisComponent(((Bounds)(ref localBounds)).max, horiz) - num3 * 0.65f - 0.07f);
			SetAxisComponent(ref v, vert, AxisComponent(((Bounds)(ref localBounds)).min, vert) + num3 * 0.65f + 0.3f);
			float outwardLocalOnAxis = GetOutwardLocalOnAxis(renderer, depth);
			float num4 = AxisComponent(((Bounds)(ref localBounds)).center, depth);
			float num5 = Mathf.Sign(outwardLocalOnAxis - num4);
			if (num5 == 0f)
			{
				num5 = 1f;
			}
			SetAxisComponent(ref v, depth, outwardLocalOnAxis + num5 * 0.02f);
			Vector3 val = ((Component)renderer).transform.TransformPoint(v);
			Vector3 localPosition = slot.Host.transform.InverseTransformPoint(val);
			Vector3 val2 = AxisUnit(depth) * num5;
			Vector3 val3 = ((Component)renderer).transform.TransformDirection(val2);
			Vector3 normalized = ((Vector3)(ref val3)).normalized;
			GameObject val4 = new GameObject("CrewMonitor_CycleButton");
			val4.transform.SetParent(slot.Host.transform, false);
			val4.transform.localPosition = localPosition;
			val4.transform.localRotation = Quaternion.identity;
			Vector3 lossyScale = slot.Host.transform.lossyScale;
			val4.transform.localScale = new Vector3(0.065f / Mathf.Max(0.001f, Mathf.Abs(lossyScale.x)), 0.065f / Mathf.Max(0.001f, Mathf.Abs(lossyScale.y)), 0.065f / Mathf.Max(0.001f, Mathf.Abs(lossyScale.z)));
			GameObject val5 = FindVanillaSwitchButton();
			int num6 = -1;
			if ((Object)(object)val5 != (Object)null)
			{
				InteractTrigger componentInChildren = val5.GetComponentInChildren<InteractTrigger>(true);
				if ((Object)(object)componentInChildren != (Object)null)
				{
					num6 = ((Component)componentInChildren).gameObject.layer;
				}
				if (num6 <= 0)
				{
					num6 = val5.layer;
				}
			}
			if (num6 <= 0 || num6 == 8 || num6 == 30)
			{
				int num7 = LayerMask.NameToLayer("InteractableObject");
				num6 = ((num7 >= 0) ? num7 : 9);
			}
			val4.layer = num6;
			val4.tag = "InteractTrigger";
			Quaternion val6 = Quaternion.FromToRotation(Vector3.up, val4.transform.InverseTransformDirection(normalized));
			GameObject obj = GameObject.CreatePrimitive((PrimitiveType)2);
			((Object)obj).name = "CyclePadBody";
			obj.transform.SetParent(val4.transform, false);
			obj.transform.localRotation = val6;
			obj.transform.localPosition = val6 * new Vector3(0f, -0.15f, 0f);
			obj.transform.localScale = new Vector3(0.85f, 0.35f, 0.85f);
			Object.Destroy((Object)(object)obj.GetComponent<Collider>());
			ApplyBezelGreyMaterial(obj);
			MeshRenderer[] componentsInChildren = obj.GetComponentsInChildren<MeshRenderer>(true);
			foreach (MeshRenderer obj2 in componentsInChildren)
			{
				((Renderer)obj2).enabled = true;
				((Renderer)obj2).forceRenderingOff = false;
			}
			GameObject obj3 = GameObject.CreatePrimitive((PrimitiveType)2);
			((Object)obj3).name = "CyclePadFace";
			obj3.transform.SetParent(val4.transform, false);
			obj3.transform.localRotation = val6;
			obj3.transform.localPosition = val6 * new Vector3(0f, 0.22f, 0f);
			obj3.transform.localScale = new Vector3(1f, 0.06f, 1f);
			Object.Destroy((Object)(object)obj3.GetComponent<Collider>());
			ApplyWhiteButtonMaterial(obj3);
			componentsInChildren = obj3.GetComponentsInChildren<MeshRenderer>(true);
			foreach (MeshRenderer obj4 in componentsInChildren)
			{
				((Renderer)obj4).enabled = true;
				((Renderer)obj4).forceRenderingOff = false;
			}
			GameObject val7 = new GameObject("CycleHitbox");
			val7.transform.SetParent(val4.transform, false);
			val7.transform.localPosition = Vector3.zero;
			val7.transform.localRotation = Quaternion.identity;
			val7.transform.localScale = Vector3.one * 2.5f;
			val7.layer = val4.layer;
			val7.tag = "InteractTrigger";
			BoxCollider val8 = val7.AddComponent<BoxCollider>();
			((Collider)val8).enabled = true;
			((Collider)val8).isTrigger = false;
			val8.size = Vector3.one;
			InteractTrigger val9 = ConfigureInteractTrigger(val7, "Cycle crew cam : [E]");
			CrewSlotInteractBridge crewSlotInteractBridge = val7.AddComponent<CrewSlotInteractBridge>();
			crewSlotInteractBridge.Init(this, slot.Index, isCycleButton: true);
			((UnityEvent<PlayerControllerB>)(object)val9.onInteract).AddListener((UnityAction<PlayerControllerB>)crewSlotInteractBridge.OnInteract);
			if (val9.onInteractEarly != null)
			{
				((UnityEvent<PlayerControllerB>)(object)val9.onInteractEarly).AddListener((UnityAction<PlayerControllerB>)crewSlotInteractBridge.OnInteract);
			}
			val7.AddComponent<CrewButtonRaycastFallback>().Init(this, slot.Index, (Collider)(object)val8, val9);
			Plugin.Log.LogInfo((object)($"Slot {slot.Index} cycle button: worldSize={0.065f:F3} " + $"localPos={val4.transform.localPosition} worldPos={val4.transform.position} " + $"towardCabin={normalized} layer={val4.layer}({LayerMask.LayerToName(val4.layer)}) " + "triggerOnHitbox=true host=" + ((Object)slot.Host).name));
			return val4;
		}

		private static void GetScreenFaceAxes(Bounds localBounds, Transform t, out int horiz, out int vert, out int depth)
		{
			//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_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			Vector3 size = ((Bounds)(ref localBounds)).size;
			depth = 0;
			if (size.y <= size.x && size.y <= size.z)
			{
				depth = 1;
			}
			else if (size.z <= size.x && size.z <= size.y)
			{
				depth = 2;
			}
			int num = (depth + 1) % 3;
			int num2 = (depth + 2) % 3;
			Vector3 val = t.TransformDirection(AxisUnit(num));
			Vector3 normalized = ((Vector3)(ref val)).normalized;
			val = t.TransformDirection(AxisUnit(num2));
			Vector3 normalized2 = ((Vector3)(ref val)).normalized;
			if (Mathf.Abs(Vector3.Dot(normalized, Vector3.up)) >= Mathf.Abs(Vector3.Dot(normalized2, Vector3.up)))
			{
				vert = num;
				horiz = num2;
			}
			else
			{
				vert = num2;
				horiz = num;
			}
		}

		private static float AxisComponent(Vector3 v, int axis)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			return axis switch
			{
				0 => v.x, 
				1 => v.y, 
				_ => v.z, 
			};
		}

		private static void SetAxisComponent(ref Vector3 v, int axis, float value)
		{
			switch (axis)
			{
			case 0:
				v.x = value;
				break;
			case 1:
				v.y = value;
				break;
			default:
				v.z = value;
				break;
			}
		}

		private static float GetOutwardLocalOnAxis(MeshRenderer renderer, int depthAxis)
		{
			//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_0009: 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_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_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: 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_0082: 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_0089: 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_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			Bounds localBounds = ((Renderer)renderer).localBounds;
			float num = AxisComponent(((Bounds)(ref localBounds)).min, depthAxis);
			float num2 = AxisComponent(((Bounds)(ref localBounds)).max, depthAxis);
			Vector3 v2;
			Vector3 v = (v2 = ((Bounds)(ref localBounds)).center);
			SetAxisComponent(ref v2, depthAxis, num);
			SetAxisComponent(ref v, depthAxis, num2);
			Vector3 val = ((Component)renderer).transform.TransformPoint(v2);
			Vector3 val2 = ((Component)renderer).transform.TransformPoint(v);
			Vector3 val3 = val;
			GameObject val4 = GameObject.Find("Environment/HangarShip");
			if ((Object)(object)val4 != (Object)null)
			{
				val3 = val4.transform.position;
			}
			Vector3 val5 = val - val3;
			float sqrMagnitude = ((Vector3)(ref val5)).sqrMagnitude;
			val5 = val2 - val3;
			bool num3 = sqrMagnitude <= ((Vector3)(ref val5)).sqrMagnitude;
			float num4 = (num3 ? num : num2);
			float num5 = (num3 ? (-1f) : 1f);
			return num4 + num5 * 0.012f;
		}

		private static GameObject CreateWhiteCyclePadVisual(Transform parent)
		{
			//IL_0025: 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_0063: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = GameObject.CreatePrimitive((PrimitiveType)2);
			((Object)val).name = "CyclePad";
			val.transform.SetParent(parent, false);
			val.transform.localPosition = Vector3.zero;
			val.transform.localRotation = Quaternion.Euler(90f, 0f, 0f);
			val.transform.localScale = new Vector3(1f, 0.28f, 1f);
			Collider component = val.GetComponent<Collider>();
			if ((Object)(object)component != (Object)null)
			{
				Object.Destroy((Object)(object)component);
			}
			ApplyWhiteButtonMaterial(val);
			MeshRenderer[] componentsInChildren = val.GetComponentsInChildren<MeshRenderer>(true);
			foreach (MeshRenderer obj in componentsInChildren)
			{
				((Renderer)obj).enabled = true;
				((Renderer)obj).forceRenderingOff = false;
			}
			Plugin.Log.LogInfo((object)"Cycle pad visual: Unlit off-white Cylinder (desk button stand-in).");
			return val;
		}

		private static void NormalizePadLocalScale(GameObject pad)
		{
			//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_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: 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_00e0: 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_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: 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_017a: 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_0166: 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_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			MeshFilter[] componentsInChildren = pad.GetComponentsInChildren<MeshFilter>(true);
			Bounds? val = null;
			MeshFilter[] array = componentsInChildren;
			Bounds val3 = default(Bounds);
			Bounds val4 = default(Bounds);
			foreach (MeshFilter val2 in array)
			{
				if ((Object)(object)val2.sharedMesh == (Object)null)
				{
					continue;
				}
				Bounds bounds = val2.sharedMesh.bounds;
				Vector3[] array2 = (Vector3[])(object)new Vector3[8];
				Vector3 center = ((Bounds)(ref bounds)).center;
				Vector3 extents = ((Bounds)(ref bounds)).extents;
				int num = 0;
				for (int j = -1; j <= 1; j += 2)
				{
					for (int k = -1; k <= 1; k += 2)
					{
						for (int l = -1; l <= 1; l += 2)
						{
							array2[num++] = ((Component)val2).transform.TransformPoint(center + Vector3.Scale(extents, new Vector3((float)j, (float)k, (float)l)));
						}
					}
				}
				((Bounds)(ref val3))..ctor(array2[0], Vector3.zero);
				for (int m = 1; m < 8; m++)
				{
					((Bounds)(ref val3)).Encapsulate(array2[m]);
				}
				((Bounds)(ref val4))..ctor(pad.transform.InverseTransformPoint(((Bounds)(ref val3)).center), Vector3.zero);
				Vector3 val5 = pad.transform.InverseTransformVector(((Bounds)(ref val3)).size);
				((Vector3)(ref val5))..ctor(Mathf.Abs(val5.x), Mathf.Abs(val5.y), Mathf.Abs(val5.z));
				((Bounds)(ref val4)).size = val5;
				if (!val.HasValue)
				{
					val = val4;
					continue;
				}
				Bounds value = val.Value;
				((Bounds)(ref value)).Encapsulate(val4);
				val = value;
			}
			float num2 = 1f;
			if (val.HasValue)
			{
				float[] array3 = new float[3];
				Bounds value2 = val.Value;
				array3[0] = ((Bounds)(ref value2)).size.x;
				value2 = val.Value;
				array3[1] = ((Bounds)(ref value2)).size.y;
				value2 = val.Value;
				array3[2] = ((Bounds)(ref value2)).size.z;
				num2 = Mathf.Max(array3);
			}
			if (num2 < 0.0001f)
			{
				num2 = 1f;
			}
			float num3 = 1f / num2;
			pad.transform.localScale = Vector3.one * num3;
		}

		private static GameObject? FindWhiteConsoleButton()
		{
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: 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_01f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0218: Unknown result type (might be due to invalid IL or missing references)
			//IL_0224: Unknown result type (might be due to invalid IL or missing references)
			//IL_0273: Unknown result type (might be due to invalid IL or missing references)
			//IL_0278: Unknown result type (might be due to invalid IL or missing references)
			string[] array = new string[7] { "Environment/HangarShip/StartMatchLever/Button", "Environment/HangarShip/ControlPanelWTexture/Button", "Environment/HangarShip/ControlDesk/Button", "Environment/HangarShip/ShipModels2b/Button", "WhiteButton", "ButtonWhite", "RoundButton" };
			foreach (string text in array)
			{
				GameObject val = GameObject.Find(text);
				if ((Object)(object)val != (Object)null && (Object)(object)val.GetComponentInChildren<MeshFilter>(true) != (Object)null)
				{
					Plugin.Log.LogInfo((object)("FindWhiteConsoleButton: name hit '" + text + "'."));
					return PreferMeshObject(val);
				}
			}
			StartMatchLever val2 = null;
			try
			{
				val2 = Object.FindObjectOfType<StartMatchLever>();
			}
			catch
			{
			}
			Vector3 val3 = Vector3.zero;
			bool flag = false;
			if ((Object)(object)val2 != (Object)null)
			{
				val3 = ((Component)val2).transform.position;
				flag = true;
			}
			else
			{
				GameObject val4 = GameObject.Find("Environment/HangarShip/ControlPanelWTexture") ?? GameObject.Find("Environment/HangarShip/ControlDesk");
				if ((Object)(object)val4 != (Object)null)
				{
					val3 = val4.transform.position;
					flag = true;
				}
			}
			GameObject val5 = GameObject.Find("Environment/HangarShip");
			if ((Object)(object)val5 != (Object)null)
			{
				GameObject val6 = null;
				float num = float.MaxValue;
				MeshRenderer[] componentsInChildren = val5.GetComponentsInChildren<MeshRenderer>(true);
				foreach (MeshRenderer val7 in componentsInChildren)
				{
					if ((Object)(object)val7 == (Object)null || (Object)(object)((Renderer)val7).sharedMaterial == (Object)null)
					{
						continue;
					}
					string name = ((Object)((Component)val7).gameObject).name;
					string path = GetPath(((Component)val7).transform);
					if (path.IndexOf("CrewMonitor", StringComparison.OrdinalIgnoreCase) >= 0 || path.IndexOf("ShipTeleporter", StringComparison.OrdinalIgnoreCase) >= 0 || (path.IndexOf("MonitorWall", StringComparison.OrdinalIgnoreCase) >= 0 && path.IndexOf("CameraMonitorSwitchButton", StringComparison.OrdinalIgnoreCase) < 0) || name.IndexOf("Screen", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						continue;
					}
					Bounds bounds = ((Renderer)val7).bounds;
					float num2 = Mathf.Max(((Bounds)(ref bounds)).size.x, Mathf.Max(((Bounds)(ref bounds)).size.y, ((Bounds)(ref bounds)).size.z));
					float num3 = Mathf.Min(((Bounds)(ref bounds)).size.x, Mathf.Min(((Bounds)(ref bounds)).size.y, ((Bounds)(ref bounds)).size.z));
					if (!(num2 < 0.02f) && !(num2 > 0.28f) && !(num3 < num2 * 0.15f) && IsLightGreyOrWhiteMaterial(val7))
					{
						float num4 = (flag ? Vector3.Distanc