Decompiled source of CChanges v1.0.1

plugins/CChanges/DoorLockpickPlus.dll

Decompiled 8 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("ScrapVisbility")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ScrapVisbility")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("8a6853bd-bdc9-4741-95c7-5aa2c8c6a6f9")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace DoorLockpickPlus;

[BepInPlugin("YourFurnace.DoorLockpickPlus", "DoorLockpickPlus", "1.3.8")]
public class DoorLockpickPlus : BaseUnityPlugin
{
	private const string modGUID = "YourFurnace.DoorLockpickPlus";

	private const string modName = "DoorLockpickPlus";

	private const string modVersion = "1.3.8";

	private readonly Harmony harmony = new Harmony("YourFurnace.DoorLockpickPlus");

	internal static DoorLockpickPlus Instance;

	internal static ManualLogSource Log;

	internal static ConfigEntry<bool> EnableNormalDoorLockpicking;

	internal static ConfigEntry<bool> EnableBigDoorHacking;

	internal static ConfigEntry<bool> EnableBigDoorInPersonClose;

	internal static ConfigEntry<bool> DebugRollLogging;

	internal static ConfigEntry<bool> EnableLockpickSounds;

	internal static ConfigEntry<float> NormalDoorPickTime;

	internal static ConfigEntry<float> NormalDoorSuccessChance;

	internal static ConfigEntry<float> BigDoorHackTime;

	internal static ConfigEntry<float> BigDoorSuccessChance;

	internal static ConfigEntry<float> BigDoorCloseTime;

	internal static ConfigEntry<float> RetryCooldown;

	internal static ConfigEntry<float> FailFlashTime;

	internal static ConfigEntry<float> LockpickSoundVolume;

	internal static ConfigEntry<float> NormalDoorTriggerWidth;

	internal static ConfigEntry<float> NormalDoorTriggerHeight;

	internal static ConfigEntry<float> NormalDoorTriggerDepth;

	internal static ConfigEntry<float> DoorTintStrength;

	internal static ConfigEntry<float> DoorOverlayAlpha;

	internal static ConfigEntry<float> DoorEmissionStrength;

	internal static ConfigEntry<float> DoorLightStrength;

	internal static ConfigEntry<float> NormalDoorVisualMultiplier;

	internal static ConfigEntry<float> BigDoorVisualMultiplier;

	private float nextScanTime = 0f;

	private void Awake()
	{
		Instance = this;
		Log = ((BaseUnityPlugin)this).Logger;
		EnableNormalDoorLockpicking = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enable normal door lockpicking", true, "Adds a normal Lethal Company E hold prompt to locked normal doors.");
		EnableBigDoorHacking = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enable big door prying", true, "Adds a normal Lethal Company E hold prompt to closed terminal controlled big doors.");
		EnableBigDoorInPersonClose = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enable big door in-person close", true, "Adds a normal Lethal Company E hold prompt to close open terminal controlled big doors.");
		EnableLockpickSounds = ((BaseUnityPlugin)this).Config.Bind<bool>("Audio", "Enable lockpick sounds", true, "Plays the base game lockpicking sound while holding E on a locked normal door.");
		LockpickSoundVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Audio", "Lockpick sound volume", 0.75f, "Volume for lockpick, success, and fail sounds.");
		NormalDoorPickTime = ((BaseUnityPlugin)this).Config.Bind<float>("Normal Doors", "Normal door pick time", 10f, "Seconds required to lockpick a normal locked door.");
		NormalDoorSuccessChance = ((BaseUnityPlugin)this).Config.Bind<float>("Normal Doors", "Normal door success chance", 0.5f, "Chance to unlock a normal locked door. 0.50 means 50%.");
		BigDoorHackTime = ((BaseUnityPlugin)this).Config.Bind<float>("Big Doors", "Big door pry time", 25f, "Seconds required to pry open a terminal controlled big door.");
		BigDoorSuccessChance = ((BaseUnityPlugin)this).Config.Bind<float>("Big Doors", "Big door pry success chance", 0.33f, "Chance to pry open a terminal controlled big door. 0.33 means 33%.");
		BigDoorCloseTime = ((BaseUnityPlugin)this).Config.Bind<float>("Big Doors", "Big door close time", 2f, "Seconds required to close an open terminal controlled big door in person. This is always successful.");
		RetryCooldown = ((BaseUnityPlugin)this).Config.Bind<float>("Safety", "Retry cooldown", 2f, "Cooldown after a lockpick or pry attempt finishes. Helps prevent retry race conditions.");
		FailFlashTime = ((BaseUnityPlugin)this).Config.Bind<float>("Visuals", "Fail flash time", 1.5f, "How long a failed door flashes red.");
		DebugRollLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "Debug roll logging", true, "Logs lockpick and pry rolls to the BepInEx console. Leave this on while playtesting.");
		NormalDoorTriggerWidth = ((BaseUnityPlugin)this).Config.Bind<float>("Trigger Sizes", "Normal door trigger width", 2.25f, "Minimum width of the invisible lockpick interaction trigger on normal doors.");
		NormalDoorTriggerHeight = ((BaseUnityPlugin)this).Config.Bind<float>("Trigger Sizes", "Normal door trigger height", 3.5f, "Minimum height of the invisible lockpick interaction trigger on normal doors.");
		NormalDoorTriggerDepth = ((BaseUnityPlugin)this).Config.Bind<float>("Trigger Sizes", "Normal door trigger depth", 2.25f, "Minimum depth of the invisible lockpick interaction trigger on normal doors.");
		DoorTintStrength = ((BaseUnityPlugin)this).Config.Bind<float>("Door Visuals", "Door tint strength", 0.55f, "How much the real door mesh is tinted while lockpicking or failing. This belongs to DoorLockpickPlus only.");
		DoorOverlayAlpha = ((BaseUnityPlugin)this).Config.Bind<float>("Door Visuals", "Door overlay alpha", 0.18f, "Transparent overlay strength for the door mesh. Lower this if the highlight is too solid.");
		DoorEmissionStrength = ((BaseUnityPlugin)this).Config.Bind<float>("Door Visuals", "Door emission strength", 1.15f, "Emission pushed into the door material while highlighted.");
		DoorLightStrength = ((BaseUnityPlugin)this).Config.Bind<float>("Door Visuals", "Door light strength", 0.55f, "Point light strength while highlighted.");
		NormalDoorVisualMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Door Visuals", "Normal door visual multiplier", 1.35f, "Extra brightness multiplier for normal doors. Raise this if normal doors are too faint.");
		BigDoorVisualMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Door Visuals", "Big door visual multiplier", 0.35f, "Brightness multiplier for big doors. Lower this if big doors are too bright.");
		harmony.PatchAll();
		Log.LogInfo((object)"DoorLockpickPlus 1.3.8 loaded. Scene-safe big door commands and fixed door highlights enabled.");
	}

	private void OnDestroy()
	{
		harmony.UnpatchSelf();
	}

	private void Update()
	{
		if (!(Time.time < nextScanTime))
		{
			nextScanTime = Time.time + 1f;
			AttachToNormalDoors();
			AttachToBigDoors();
		}
	}

	private void AttachToNormalDoors()
	{
		if (EnableNormalDoorLockpicking == null || !EnableNormalDoorLockpicking.Value)
		{
			return;
		}
		DoorLock[] array = Object.FindObjectsOfType<DoorLock>();
		DoorLock[] array2 = array;
		foreach (DoorLock val in array2)
		{
			if (!((Object)(object)val == (Object)null) && (Object)(object)((Component)val).GetComponent<NormalDoorLockpickTarget>() == (Object)null)
			{
				NormalDoorLockpickTarget normalDoorLockpickTarget = ((Component)val).gameObject.AddComponent<NormalDoorLockpickTarget>();
				normalDoorLockpickTarget.Init(val);
			}
		}
	}

	private void AttachToBigDoors()
	{
		if ((EnableBigDoorHacking == null || !EnableBigDoorHacking.Value) && (EnableBigDoorInPersonClose == null || !EnableBigDoorInPersonClose.Value))
		{
			return;
		}
		TerminalAccessibleObject[] array = Object.FindObjectsOfType<TerminalAccessibleObject>();
		TerminalAccessibleObject[] array2 = array;
		foreach (TerminalAccessibleObject val in array2)
		{
			if (!((Object)(object)val == (Object)null) && BigDoorUtil.IsProbablyBigDoor(val) && (Object)(object)((Component)val).GetComponent<BigDoorLockpickTarget>() == (Object)null)
			{
				BigDoorLockpickTarget bigDoorLockpickTarget = ((Component)val).gameObject.AddComponent<BigDoorLockpickTarget>();
				bigDoorLockpickTarget.Init(val);
			}
		}
	}

	internal static void ShowTip(string header, string body, bool warning)
	{
		try
		{
			HUDManager val = Object.FindObjectOfType<HUDManager>();
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			MethodInfo methodInfo = AccessTools.Method(typeof(HUDManager), "DisplayTip", new Type[5]
			{
				typeof(string),
				typeof(string),
				typeof(bool),
				typeof(bool),
				typeof(string)
			}, (Type[])null);
			if (methodInfo != null)
			{
				methodInfo.Invoke(val, new object[5] { header, body, warning, false, "DoorLockpickPlus" });
				return;
			}
			MethodInfo methodInfo2 = AccessTools.Method(typeof(HUDManager), "DisplayTip", (Type[])null, (Type[])null);
			if (methodInfo2 == null)
			{
				return;
			}
			ParameterInfo[] parameters = methodInfo2.GetParameters();
			object[] array = new object[parameters.Length];
			int num = 0;
			for (int i = 0; i < parameters.Length; i++)
			{
				Type parameterType = parameters[i].ParameterType;
				if (parameterType == typeof(string))
				{
					switch (num)
					{
					case 0:
						array[i] = header;
						break;
					case 1:
						array[i] = body;
						break;
					default:
						array[i] = "DoorLockpickPlus";
						break;
					}
					num++;
				}
				else if (parameterType == typeof(bool))
				{
					array[i] = warning;
				}
				else
				{
					array[i] = null;
				}
			}
			methodInfo2.Invoke(val, array);
		}
		catch
		{
		}
	}

	internal static Color YellowHighlight()
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		return new Color(1f, 0.78f, 0.08f, 1f);
	}

	internal static Color RedHighlight()
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		return new Color(1f, 0.12f, 0.08f, 1f);
	}
}
internal class NormalDoorLockpickTarget : MonoBehaviour
{
	[CompilerGenerated]
	private sealed class <EndOfFrameUnlockGuard>d__21 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public NormalDoorLockpickTarget <>4__this;

		object IEnumerator<object>.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		object IEnumerator.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		[DebuggerHidden]
		public <EndOfFrameUnlockGuard>d__21(int <>1__state)
		{
			this.<>1__state = <>1__state;
		}

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected O, but got Unknown
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				break;
			case 1:
				<>1__state = -1;
				<>4__this.MaintainDoorUnlockedState();
				break;
			}
			if (<>4__this.unlockedByThisMod && (Object)(object)<>4__this.door != (Object)null)
			{
				<>2__current = (object)new WaitForEndOfFrame();
				<>1__state = 1;
				return true;
			}
			return false;
		}

		bool IEnumerator.MoveNext()
		{
			//ILSpy generated this explicit interface implementation from .override directive in MoveNext
			return this.MoveNext();
		}

		[DebuggerHidden]
		void IEnumerator.Reset()
		{
			throw new NotSupportedException();
		}
	}

	private DoorLock door;

	private DoorVisualHighlighter highlighter;

	private DoorAudioController audioController;

	private readonly List<InteractTrigger> vanillaTriggers = new List<InteractTrigger>();

	private readonly Dictionary<InteractTrigger, TriggerSnapshot> vanillaSnapshots = new Dictionary<InteractTrigger, TriggerSnapshot>();

	private GameObject customTriggerObject;

	private InteractTrigger customTrigger;

	private float cooldownUntil = 0f;

	private float redFlashUntil = 0f;

	private bool resolvingAttempt = false;

	private bool unlockedByThisMod = false;

	private bool unlockGuardStarted = false;

	private bool unlockMethodsCalled = false;

	private bool wasHoldingLockpick = false;

	public void Init(DoorLock targetDoor)
	{
		//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_002c: Unknown result type (might be due to invalid IL or missing references)
		door = targetDoor;
		Bounds doorFocusBounds = GetDoorFocusBounds();
		highlighter = ((Component)this).gameObject.AddComponent<DoorVisualHighlighter>();
		highlighter.Init(((Component)this).gameObject, doorFocusBounds, bigDoor: false);
		audioController = ((Component)this).gameObject.AddComponent<DoorAudioController>();
		audioController.Init(door);
		CacheVanillaTriggers();
		CreateCustomTrigger();
	}

	private Bounds GetDoorFocusBounds()
	{
		//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_0018: 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_00c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
		Bounds bounds = default(Bounds);
		((Bounds)(ref bounds))..ctor(((Component)this).transform.position, Vector3.one * 2f);
		bool hasBounds = false;
		if ((Object)(object)door != (Object)null && (Object)(object)door.doorTrigger != (Object)null)
		{
			BoundsUtil.EncapsulateTransformBounds(((Component)door.doorTrigger).transform, ref bounds, ref hasBounds);
		}
		if ((Object)(object)door != (Object)null && (Object)(object)door.doorTriggerB != (Object)null)
		{
			BoundsUtil.EncapsulateTransformBounds(((Component)door.doorTriggerB).transform, ref bounds, ref hasBounds);
		}
		if (!hasBounds)
		{
			bounds = BoundsUtil.GetBounds(((Component)this).gameObject);
			return bounds;
		}
		return bounds;
	}

	private void CacheVanillaTriggers()
	{
		TryAddVanillaTrigger(door.doorTrigger);
		TryAddVanillaTrigger(door.doorTriggerB);
		InteractTrigger[] componentsInChildren = ((Component)door).GetComponentsInChildren<InteractTrigger>(true);
		InteractTrigger[] array = componentsInChildren;
		foreach (InteractTrigger trigger in array)
		{
			TryAddVanillaTrigger(trigger);
		}
	}

	private void TryAddVanillaTrigger(InteractTrigger trigger)
	{
		if (!((Object)(object)trigger == (Object)null) && !vanillaTriggers.Contains(trigger))
		{
			vanillaTriggers.Add(trigger);
			vanillaSnapshots[trigger] = new TriggerSnapshot(trigger);
		}
	}

	private void CreateCustomTrigger()
	{
		//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_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Expected O, but got Unknown
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: 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_00a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: Unknown result type (might be due to invalid IL or missing references)
		Bounds doorFocusBounds = GetDoorFocusBounds();
		customTriggerObject = new GameObject("DoorLockpickPlus_NormalDoor_InteractTrigger");
		customTriggerObject.transform.position = ((Bounds)(ref doorFocusBounds)).center;
		customTriggerObject.transform.rotation = Quaternion.identity;
		BoxCollider val = customTriggerObject.AddComponent<BoxCollider>();
		((Collider)val).isTrigger = true;
		val.size = new Vector3(Mathf.Max(DoorLockpickPlus.NormalDoorTriggerWidth.Value, ((Bounds)(ref doorFocusBounds)).size.x + 1f), Mathf.Max(DoorLockpickPlus.NormalDoorTriggerHeight.Value, ((Bounds)(ref doorFocusBounds)).size.y + 0.8f), Mathf.Max(DoorLockpickPlus.NormalDoorTriggerDepth.Value, ((Bounds)(ref doorFocusBounds)).size.z + 1f));
		InteractTriggerUtil.MakeGameObjectARealInteractTrigger(customTriggerObject);
		customTrigger = customTriggerObject.AddComponent<InteractTrigger>();
		InteractTriggerUtil.ConfigureBaseTrigger(customTrigger);
		InteractTriggerUtil.CopyIconFromTriggers(customTrigger, vanillaTriggers);
		InteractTriggerUtil.AddInteractListener(customTrigger, OnDoorInteract);
		customTriggerObject.SetActive(false);
	}

	private void Update()
	{
		//IL_0106: 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)
		if ((Object)(object)door == (Object)null)
		{
			ClearAll();
			return;
		}
		if (unlockedByThisMod)
		{
			StopLockpickLoopIfNeeded();
			MaintainDoorUnlockedState();
			ConfigureUnlockedVanillaTriggers();
			SetCustomTriggerActive(active: false);
			highlighter.Clear();
			return;
		}
		if (!IsLocked())
		{
			StopLockpickLoopIfNeeded();
			ConfigureUnlockedVanillaTriggers();
			SetCustomTriggerActive(active: false);
			highlighter.Clear();
			return;
		}
		DisableVanillaTriggersWhileLocked();
		UpdateCustomTriggerPosition();
		bool flag = Time.time < cooldownUntil;
		bool flag2 = (Object)(object)customTrigger != (Object)null && customTrigger.isBeingHeldByPlayer;
		ConfigureCustomTrigger(flag);
		UpdateLockpickLoop(flag2 && !flag && !resolvingAttempt);
		if (Time.time < redFlashUntil)
		{
			highlighter.Apply(DoorLockpickPlus.RedHighlight(), 1f, enableLight: true, DoorLockpickPlus.NormalDoorVisualMultiplier.Value);
		}
		else if (flag2 || resolvingAttempt)
		{
			highlighter.Apply(DoorLockpickPlus.YellowHighlight(), 1f, enableLight: true, DoorLockpickPlus.NormalDoorVisualMultiplier.Value);
		}
		else
		{
			highlighter.Clear();
		}
	}

	private void LateUpdate()
	{
		if (unlockedByThisMod)
		{
			MaintainDoorUnlockedState();
		}
	}

	[IteratorStateMachine(typeof(<EndOfFrameUnlockGuard>d__21))]
	private IEnumerator EndOfFrameUnlockGuard()
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <EndOfFrameUnlockGuard>d__21(0)
		{
			<>4__this = this
		};
	}

	private void UpdateLockpickLoop(bool shouldPlay)
	{
		if (DoorLockpickPlus.EnableLockpickSounds == null || !DoorLockpickPlus.EnableLockpickSounds.Value)
		{
			StopLockpickLoopIfNeeded();
		}
		else if (shouldPlay)
		{
			if (!wasHoldingLockpick)
			{
				wasHoldingLockpick = true;
				if ((Object)(object)audioController != (Object)null)
				{
					audioController.StartLockpickLoop();
				}
			}
		}
		else
		{
			StopLockpickLoopIfNeeded();
		}
	}

	private void StopLockpickLoopIfNeeded()
	{
		if (wasHoldingLockpick)
		{
			wasHoldingLockpick = false;
			if ((Object)(object)audioController != (Object)null)
			{
				audioController.StopLockpickLoop();
			}
		}
	}

	private void UpdateCustomTriggerPosition()
	{
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_0071: 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_00b3: 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)
		if (!((Object)(object)customTriggerObject == (Object)null))
		{
			Bounds doorFocusBounds = GetDoorFocusBounds();
			customTriggerObject.transform.position = ((Bounds)(ref doorFocusBounds)).center;
			customTriggerObject.transform.rotation = Quaternion.identity;
			BoxCollider component = customTriggerObject.GetComponent<BoxCollider>();
			if ((Object)(object)component != (Object)null)
			{
				component.size = new Vector3(Mathf.Max(DoorLockpickPlus.NormalDoorTriggerWidth.Value, ((Bounds)(ref doorFocusBounds)).size.x + 1f), Mathf.Max(DoorLockpickPlus.NormalDoorTriggerHeight.Value, ((Bounds)(ref doorFocusBounds)).size.y + 0.8f), Mathf.Max(DoorLockpickPlus.NormalDoorTriggerDepth.Value, ((Bounds)(ref doorFocusBounds)).size.z + 1f));
			}
			InteractTriggerUtil.MakeGameObjectARealInteractTrigger(customTriggerObject);
		}
	}

	private void ConfigureCustomTrigger(bool inCooldown)
	{
		if (!((Object)(object)customTrigger == (Object)null))
		{
			InteractTriggerUtil.ConfigureBaseTrigger(customTrigger);
			customTrigger.interactable = !inCooldown && !resolvingAttempt;
			customTrigger.timeToHold = Mathf.Max(0.1f, DoorLockpickPlus.NormalDoorPickTime.Value);
			customTrigger.hoverTip = (inCooldown ? "Lockpick cooling down..." : "Pick lock");
			customTrigger.holdTip = "Lockpicking...";
			SetCustomTriggerActive(active: true);
		}
	}

	private void SetCustomTriggerActive(bool active)
	{
		if ((Object)(object)customTriggerObject != (Object)null && customTriggerObject.activeSelf != active)
		{
			customTriggerObject.SetActive(active);
		}
	}

	private void DisableVanillaTriggersWhileLocked()
	{
		foreach (InteractTrigger vanillaTrigger in vanillaTriggers)
		{
			if (!((Object)(object)vanillaTrigger == (Object)null))
			{
				vanillaTrigger.interactable = false;
				vanillaTrigger.hoverTip = "Locked";
				vanillaTrigger.holdTip = "Locked";
			}
		}
	}

	private void RestoreVanillaTriggers()
	{
		foreach (KeyValuePair<InteractTrigger, TriggerSnapshot> vanillaSnapshot in vanillaSnapshots)
		{
			if ((Object)(object)vanillaSnapshot.Key != (Object)null)
			{
				vanillaSnapshot.Value.Restore(vanillaSnapshot.Key);
			}
		}
	}

	private void OnDoorInteract(PlayerControllerB player)
	{
		if ((Object)(object)door == (Object)null || (Object)(object)player == (Object)null)
		{
			return;
		}
		StopLockpickLoopIfNeeded();
		if (!IsLocked())
		{
			return;
		}
		if (resolvingAttempt || Time.time < cooldownUntil)
		{
			DoorLockpickPlus.ShowTip("Lockpick", "Wait a moment before trying again.", warning: true);
			return;
		}
		resolvingAttempt = true;
		float num = Mathf.Clamp01(DoorLockpickPlus.NormalDoorSuccessChance.Value);
		float num2 = Random.Range(0f, 1f);
		bool flag = num2 <= num;
		if (DoorLockpickPlus.DebugRollLogging != null && DoorLockpickPlus.DebugRollLogging.Value && DoorLockpickPlus.Log != null)
		{
			DoorLockpickPlus.Log.LogInfo((object)("Normal door lockpick roll: " + num2.ToString("0.000") + " / chance " + num.ToString("0.000") + " / success " + flag));
		}
		if (flag)
		{
			unlockedByThisMod = true;
			unlockMethodsCalled = false;
			CallKeyStyleUnlockOnce();
			MaintainDoorUnlockedState();
			ConfigureUnlockedVanillaTriggers();
			SetCustomTriggerActive(active: false);
			if ((Object)(object)audioController != (Object)null)
			{
				audioController.PlayUnlockSoundOnce();
			}
			if (!unlockGuardStarted)
			{
				unlockGuardStarted = true;
				((MonoBehaviour)this).StartCoroutine(EndOfFrameUnlockGuard());
			}
			DoorLockpickPlus.ShowTip("Lockpick Success", "The door unlocked.", warning: false);
			cooldownUntil = Time.time + 0.5f;
		}
		else
		{
			if ((Object)(object)audioController != (Object)null)
			{
				audioController.PlayFailSoundOnce();
			}
			DoorLockpickPlus.ShowTip("Lockpick Failed", "The lock held. Try again.", warning: true);
			redFlashUntil = Time.time + Mathf.Max(0.1f, DoorLockpickPlus.FailFlashTime.Value);
			cooldownUntil = Time.time + Mathf.Max(0.1f, DoorLockpickPlus.RetryCooldown.Value);
		}
		resolvingAttempt = false;
	}

	private bool IsLocked()
	{
		if ((Object)(object)door == (Object)null)
		{
			return false;
		}
		return door.isLocked;
	}

	private void CallKeyStyleUnlockOnce()
	{
		if (!((Object)(object)door == (Object)null) && !unlockMethodsCalled)
		{
			unlockMethodsCalled = true;
			CallUnlockMethodsOnDoor(door);
			if ((Object)(object)door.twinDoor != (Object)null)
			{
				CallUnlockMethodsOnDoor(door.twinDoor);
			}
		}
	}

	private void CallUnlockMethodsOnDoor(DoorLock targetDoor)
	{
		if (!((Object)(object)targetDoor == (Object)null) && !ReflectionUtil.CallNoArgExact(targetDoor, "UnlockDoorSyncWithServer"))
		{
			ReflectionUtil.CallNoArgExact(targetDoor, "UnlockDoor");
			ReflectionUtil.CallNoArgExact(targetDoor, "UnlockDoorServerRpc");
		}
	}

	private void MaintainDoorUnlockedState()
	{
		MaintainDoorUnlockedStateFor(door);
		if ((Object)(object)door != (Object)null && (Object)(object)door.twinDoor != (Object)null)
		{
			MaintainDoorUnlockedStateFor(door.twinDoor);
		}
	}

	private void MaintainDoorUnlockedStateFor(DoorLock targetDoor)
	{
		if (!((Object)(object)targetDoor == (Object)null))
		{
			targetDoor.isLocked = false;
			targetDoor.isPickingLock = false;
			targetDoor.lockPickTimeLeft = 0f;
			targetDoor.canBeLocked = false;
			if ((Object)(object)targetDoor.doorTrigger != (Object)null)
			{
				targetDoor.doorTrigger.interactable = true;
				targetDoor.doorTrigger.timeToHoldSpeedMultiplier = 1f;
				targetDoor.doorTrigger.timeToHold = targetDoor.defaultTimeToHold;
			}
			if ((Object)(object)targetDoor.doorTriggerB != (Object)null)
			{
				targetDoor.doorTriggerB.interactable = true;
				targetDoor.doorTriggerB.timeToHoldSpeedMultiplier = 1f;
				targetDoor.doorTriggerB.timeToHold = targetDoor.defaultTimeToHold;
			}
		}
	}

	private void ConfigureUnlockedVanillaTriggers()
	{
		ConfigureUnlockedVanillaTriggersFor(door);
		if ((Object)(object)door != (Object)null && (Object)(object)door.twinDoor != (Object)null)
		{
			ConfigureUnlockedVanillaTriggersFor(door.twinDoor);
		}
	}

	private void ConfigureUnlockedVanillaTriggersFor(DoorLock targetDoor)
	{
		if (!((Object)(object)targetDoor == (Object)null))
		{
			if ((Object)(object)targetDoor.doorTrigger != (Object)null)
			{
				targetDoor.doorTrigger.interactable = true;
				targetDoor.doorTrigger.oneHandedItemAllowed = true;
				targetDoor.doorTrigger.twoHandedItemAllowed = true;
				targetDoor.doorTrigger.timeToHoldSpeedMultiplier = 1f;
				targetDoor.doorTrigger.timeToHold = targetDoor.defaultTimeToHold;
			}
			if ((Object)(object)targetDoor.doorTriggerB != (Object)null)
			{
				targetDoor.doorTriggerB.interactable = true;
				targetDoor.doorTriggerB.oneHandedItemAllowed = true;
				targetDoor.doorTriggerB.twoHandedItemAllowed = true;
				targetDoor.doorTriggerB.timeToHoldSpeedMultiplier = 1f;
				targetDoor.doorTriggerB.timeToHold = targetDoor.defaultTimeToHold;
			}
		}
	}

	private void ClearAll()
	{
		StopLockpickLoopIfNeeded();
		RestoreVanillaTriggers();
		if ((Object)(object)customTriggerObject != (Object)null)
		{
			Object.Destroy((Object)(object)customTriggerObject);
			customTriggerObject = null;
		}
		if ((Object)(object)highlighter != (Object)null)
		{
			highlighter.Clear();
		}
	}

	private void OnDestroy()
	{
		ClearAll();
	}
}
internal class BigDoorLockpickTarget : MonoBehaviour
{
	[CompilerGenerated]
	private sealed class <ExecuteBigDoorCommand>d__20 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public bool targetOpen;

		public BigDoorLockpickTarget <>4__this;

		private bool <beforeOpen>5__1;

		private bool <afterTerminal>5__2;

		private bool <actualOpen>5__3;

		object IEnumerator<object>.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		object IEnumerator.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		[DebuggerHidden]
		public <ExecuteBigDoorCommand>d__20(int <>1__state)
		{
			this.<>1__state = <>1__state;
		}

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			//IL_0224: Unknown result type (might be due to invalid IL or missing references)
			//IL_022e: Expected O, but got Unknown
			//IL_0294: Unknown result type (might be due to invalid IL or missing references)
			//IL_029e: Expected O, but got Unknown
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Expected O, but got Unknown
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				if ((Object)(object)<>4__this.bigDoor == (Object)null)
				{
					<>4__this.resolvingAttempt = false;
					return false;
				}
				<beforeOpen>5__1 = BigDoorUtil.IsOpen(<>4__this.bigDoor);
				if (<beforeOpen>5__1 == targetOpen)
				{
					if (targetOpen)
					{
						DoorLockpickPlus.ShowTip("Big Door", "The big door is already open.", warning: false);
					}
					else
					{
						DoorLockpickPlus.ShowTip("Big Door", "The big door is already closed.", warning: false);
					}
					<>4__this.cooldownUntil = Time.time + 0.5f;
					<>4__this.resolvingAttempt = false;
					return false;
				}
				if (DoorLockpickPlus.DebugRollLogging != null && DoorLockpickPlus.DebugRollLogging.Value && DoorLockpickPlus.Log != null)
				{
					DoorLockpickPlus.Log.LogInfo((object)("Big door command start. targetOpen=" + targetOpen + " beforeOpen=" + <beforeOpen>5__1 + " code=" + BigDoorUtil.GetObjectCode(<>4__this.bigDoor)));
				}
				BigDoorUtil.ClearCooldown(<>4__this.bigDoor);
				BigDoorUtil.SendTerminalCommand(<>4__this.bigDoor);
				<>2__current = (object)new WaitForSeconds(0.35f);
				<>1__state = 1;
				return true;
			case 1:
				<>1__state = -1;
				if ((Object)(object)<>4__this.bigDoor == (Object)null)
				{
					<>4__this.resolvingAttempt = false;
					return false;
				}
				<afterTerminal>5__2 = BigDoorUtil.IsOpen(<>4__this.bigDoor);
				if (<afterTerminal>5__2 != targetOpen)
				{
					BigDoorUtil.ClearCooldown(<>4__this.bigDoor);
					BigDoorUtil.ForceSetOpen(<>4__this.bigDoor, targetOpen);
					<>2__current = (object)new WaitForSeconds(0.2f);
					<>1__state = 2;
					return true;
				}
				goto IL_023f;
			case 2:
				<>1__state = -1;
				goto IL_023f;
			case 3:
				{
					<>1__state = -1;
					break;
				}
				IL_023f:
				if ((Object)(object)<>4__this.bigDoor != (Object)null && BigDoorUtil.IsOpen(<>4__this.bigDoor) != targetOpen)
				{
					BigDoorUtil.ForceSetOpen(<>4__this.bigDoor, targetOpen);
					<>2__current = (object)new WaitForSeconds(0.1f);
					<>1__state = 3;
					return true;
				}
				break;
			}
			<actualOpen>5__3 = (Object)(object)<>4__this.bigDoor != (Object)null && BigDoorUtil.IsOpen(<>4__this.bigDoor);
			if (DoorLockpickPlus.DebugRollLogging != null && DoorLockpickPlus.DebugRollLogging.Value && DoorLockpickPlus.Log != null)
			{
				DoorLockpickPlus.Log.LogInfo((object)("Big door command end. targetOpen=" + targetOpen + " actualOpen=" + <actualOpen>5__3));
			}
			if (<actualOpen>5__3 == targetOpen)
			{
				if (targetOpen)
				{
					DoorLockpickPlus.ShowTip("Pry Success", "The big door opened.", warning: false);
				}
				else
				{
					DoorLockpickPlus.ShowTip("Big Door Closed", "The big door closed.", warning: false);
				}
			}
			else
			{
				DoorLockpickPlus.ShowTip("Door Command Failed", "The command ran but the door did not reach the expected state.", warning: true);
			}
			<>4__this.cooldownUntil = Time.time + 0.5f;
			<>4__this.resolvingAttempt = false;
			return false;
		}

		bool IEnumerator.MoveNext()
		{
			//ILSpy generated this explicit interface implementation from .override directive in MoveNext
			return this.MoveNext();
		}

		[DebuggerHidden]
		void IEnumerator.Reset()
		{
			throw new NotSupportedException();
		}
	}

	private TerminalAccessibleObject bigDoor;

	private DoorVisualHighlighter highlighter;

	private readonly List<InteractTrigger> triggers = new List<InteractTrigger>();

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

	private float cooldownUntil = 0f;

	private float redFlashUntil = 0f;

	private bool resolvingAttempt = false;

	private float nextTriggerRefreshTime = 0f;

	private int lastBoundsSignature = 0;

	public void Init(TerminalAccessibleObject targetDoor)
	{
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		bigDoor = targetDoor;
		Bounds bounds = BoundsUtil.GetBounds(((Component)this).gameObject);
		highlighter = ((Component)this).gameObject.AddComponent<DoorVisualHighlighter>();
		highlighter.Init(((Component)this).gameObject, bounds, bigDoor: true);
		RebuildSurfaceTriggers();
	}

	private void Update()
	{
		//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_010c: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)bigDoor == (Object)null || (Object)(object)((Component)bigDoor).gameObject == (Object)null)
		{
			Clear();
			return;
		}
		if (!((Component)bigDoor).gameObject.activeInHierarchy)
		{
			Clear();
			return;
		}
		if (Time.time >= nextTriggerRefreshTime)
		{
			nextTriggerRefreshTime = Time.time + 0.75f;
			RebuildSurfaceTriggersIfNeeded();
		}
		bool isOpen = BigDoorUtil.IsOpen(bigDoor);
		bool inCooldown = Time.time < cooldownUntil;
		bool flag = AnyTriggerHeld();
		UpdateTriggerTransforms();
		ConfigureTriggers(isOpen, inCooldown);
		if (Time.time < redFlashUntil)
		{
			highlighter.Apply(DoorLockpickPlus.RedHighlight(), 1f, enableLight: true, DoorLockpickPlus.BigDoorVisualMultiplier.Value);
		}
		else if (flag || resolvingAttempt)
		{
			highlighter.Apply(DoorLockpickPlus.YellowHighlight(), 1f, enableLight: true, DoorLockpickPlus.BigDoorVisualMultiplier.Value);
		}
		else
		{
			highlighter.Clear();
		}
	}

	private bool AnyTriggerHeld()
	{
		for (int i = 0; i < triggers.Count; i++)
		{
			if ((Object)(object)triggers[i] != (Object)null && triggers[i].isBeingHeldByPlayer)
			{
				return true;
			}
		}
		return false;
	}

	private void RebuildSurfaceTriggersIfNeeded()
	{
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		List<Bounds> individualVisualBounds = BoundsUtil.GetIndividualVisualBounds(((Component)this).gameObject, bigDoor: true);
		if (individualVisualBounds.Count == 0)
		{
			individualVisualBounds.Add(BoundsUtil.GetBounds(((Component)this).gameObject));
		}
		int num = Mathf.Clamp(individualVisualBounds.Count, 1, 8);
		int boundsSignature = GetBoundsSignature(individualVisualBounds, num);
		if (num != triggerObjects.Count || boundsSignature != lastBoundsSignature)
		{
			RebuildSurfaceTriggers();
		}
	}

	private int GetBoundsSignature(List<Bounds> boundsList, int count)
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
		int num = 17;
		num = num * 31 + count;
		for (int i = 0; i < count && i < boundsList.Count; i++)
		{
			Bounds val = boundsList[i];
			num = num * 31 + Mathf.RoundToInt(((Bounds)(ref val)).center.x * 10f);
			num = num * 31 + Mathf.RoundToInt(((Bounds)(ref val)).center.y * 10f);
			num = num * 31 + Mathf.RoundToInt(((Bounds)(ref val)).center.z * 10f);
			num = num * 31 + Mathf.RoundToInt(((Bounds)(ref val)).size.x * 10f);
			num = num * 31 + Mathf.RoundToInt(((Bounds)(ref val)).size.y * 10f);
			num = num * 31 + Mathf.RoundToInt(((Bounds)(ref val)).size.z * 10f);
		}
		return num;
	}

	private void RebuildSurfaceTriggers()
	{
		//IL_0053: 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)
		DestroyTriggers();
		if (!((Object)(object)bigDoor == (Object)null) && !((Object)(object)((Component)bigDoor).gameObject == (Object)null))
		{
			List<Bounds> individualVisualBounds = BoundsUtil.GetIndividualVisualBounds(((Component)this).gameObject, bigDoor: true);
			if (individualVisualBounds.Count == 0)
			{
				individualVisualBounds.Add(BoundsUtil.GetBounds(((Component)this).gameObject));
			}
			int num = Mathf.Clamp(individualVisualBounds.Count, 1, 8);
			lastBoundsSignature = GetBoundsSignature(individualVisualBounds, num);
			for (int i = 0; i < num; i++)
			{
				CreateSurfaceTrigger(i, individualVisualBounds[i]);
			}
			UpdateTriggerTransforms();
		}
	}

	private void CreateSurfaceTrigger(int index, Bounds bounds)
	{
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Expected O, but got Unknown
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject("DoorLockpickPlus_BigDoor_SurfaceTrigger_" + index);
		if ((Object)(object)bigDoor != (Object)null)
		{
			val.transform.SetParent(((Component)bigDoor).transform, true);
		}
		BoxCollider val2 = val.AddComponent<BoxCollider>();
		((Collider)val2).isTrigger = true;
		ConfigureSurfaceBox(val2, bounds);
		InteractTriggerUtil.MakeGameObjectARealInteractTrigger(val);
		InteractTrigger val3 = val.AddComponent<InteractTrigger>();
		InteractTriggerUtil.ConfigureBaseTrigger(val3);
		InteractTriggerUtil.CopyIconFromScene(val3);
		InteractTriggerUtil.AddInteractListener(val3, OnBigDoorInteract);
		triggerObjects.Add(val);
		triggers.Add(val3);
	}

	private void UpdateTriggerTransforms()
	{
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ea: 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_0100: 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)
		if ((Object)(object)bigDoor == (Object)null || (Object)(object)((Component)bigDoor).gameObject == (Object)null)
		{
			return;
		}
		List<Bounds> individualVisualBounds = BoundsUtil.GetIndividualVisualBounds(((Component)this).gameObject, bigDoor: true);
		if (individualVisualBounds.Count == 0)
		{
			individualVisualBounds.Add(BoundsUtil.GetBounds(((Component)this).gameObject));
		}
		int num = Mathf.Min(triggerObjects.Count, individualVisualBounds.Count);
		for (int i = 0; i < num; i++)
		{
			GameObject val = triggerObjects[i];
			if (!((Object)(object)val == (Object)null))
			{
				if ((Object)(object)val.transform.parent != (Object)(object)((Component)bigDoor).transform)
				{
					val.transform.SetParent(((Component)bigDoor).transform, true);
				}
				Transform transform = val.transform;
				Bounds val2 = individualVisualBounds[i];
				transform.position = ((Bounds)(ref val2)).center;
				val.transform.rotation = Quaternion.identity;
				BoxCollider component = val.GetComponent<BoxCollider>();
				if ((Object)(object)component != (Object)null)
				{
					ConfigureSurfaceBox(component, individualVisualBounds[i]);
				}
				InteractTriggerUtil.MakeGameObjectARealInteractTrigger(val);
			}
		}
	}

	private void ConfigureSurfaceBox(BoxCollider box, Bounds bounds)
	{
		//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_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)box == (Object)null))
		{
			Vector3 size = ((Bounds)(ref bounds)).size;
			size.x = Mathf.Max(0.6f, size.x);
			size.y = Mathf.Max(1.2f, size.y);
			size.z = Mathf.Max(0.45f, size.z);
			box.center = Vector3.zero;
			box.size = size;
		}
	}

	private void ConfigureTriggers(bool isOpen, bool inCooldown)
	{
		bool flag = false;
		float timeToHold = 1f;
		string hoverTip = "";
		string holdTip = "";
		if (isOpen && DoorLockpickPlus.EnableBigDoorInPersonClose.Value)
		{
			flag = true;
			timeToHold = Mathf.Max(0.1f, DoorLockpickPlus.BigDoorCloseTime.Value);
			hoverTip = (inCooldown ? "Door controls cooling down..." : "Close big door");
			holdTip = "Closing door...";
		}
		else if (!isOpen && DoorLockpickPlus.EnableBigDoorHacking.Value)
		{
			flag = true;
			timeToHold = Mathf.Max(0.1f, DoorLockpickPlus.BigDoorHackTime.Value);
			hoverTip = (inCooldown ? "Pry attempt cooling down..." : "Pry open big door");
			holdTip = "Attempting to pry open...";
		}
		for (int i = 0; i < triggers.Count; i++)
		{
			InteractTrigger val = triggers[i];
			if (!((Object)(object)val == (Object)null))
			{
				InteractTriggerUtil.ConfigureBaseTrigger(val);
				val.interactable = flag && !inCooldown && !resolvingAttempt;
				val.timeToHold = timeToHold;
				val.hoverTip = hoverTip;
				val.holdTip = holdTip;
			}
		}
	}

	private void OnBigDoorInteract(PlayerControllerB player)
	{
		if ((Object)(object)bigDoor == (Object)null || (Object)(object)player == (Object)null)
		{
			resolvingAttempt = false;
			return;
		}
		if (resolvingAttempt || Time.time < cooldownUntil)
		{
			DoorLockpickPlus.ShowTip("Door Controls", "Wait a moment before trying again.", warning: true);
			return;
		}
		resolvingAttempt = true;
		bool flag = BigDoorUtil.IsOpen(bigDoor);
		if (DoorLockpickPlus.DebugRollLogging != null && DoorLockpickPlus.DebugRollLogging.Value && DoorLockpickPlus.Log != null)
		{
			DoorLockpickPlus.Log.LogInfo((object)("Big door interact on " + ((Object)bigDoor).name + " / current open " + flag));
		}
		if (flag)
		{
			((MonoBehaviour)this).StartCoroutine(ExecuteBigDoorCommand(targetOpen: false));
			return;
		}
		float num = Mathf.Clamp01(DoorLockpickPlus.BigDoorSuccessChance.Value);
		float num2 = Random.Range(0f, 1f);
		bool flag2 = num2 <= num;
		if (DoorLockpickPlus.DebugRollLogging != null && DoorLockpickPlus.DebugRollLogging.Value && DoorLockpickPlus.Log != null)
		{
			DoorLockpickPlus.Log.LogInfo((object)("Big door pry roll: " + num2.ToString("0.000") + " / chance " + num.ToString("0.000") + " / success " + flag2));
		}
		if (flag2)
		{
			((MonoBehaviour)this).StartCoroutine(ExecuteBigDoorCommand(targetOpen: true));
			return;
		}
		DoorLockpickPlus.ShowTip("Pry Failed", "You failed to pry it open. Try again.", warning: true);
		redFlashUntil = Time.time + Mathf.Max(0.1f, DoorLockpickPlus.FailFlashTime.Value);
		cooldownUntil = Time.time + Mathf.Max(0.1f, DoorLockpickPlus.RetryCooldown.Value);
		resolvingAttempt = false;
	}

	[IteratorStateMachine(typeof(<ExecuteBigDoorCommand>d__20))]
	private IEnumerator ExecuteBigDoorCommand(bool targetOpen)
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <ExecuteBigDoorCommand>d__20(0)
		{
			<>4__this = this,
			targetOpen = targetOpen
		};
	}

	private void DestroyTriggers()
	{
		for (int i = 0; i < triggerObjects.Count; i++)
		{
			if ((Object)(object)triggerObjects[i] != (Object)null)
			{
				Object.Destroy((Object)(object)triggerObjects[i]);
			}
		}
		triggerObjects.Clear();
		triggers.Clear();
	}

	private void Clear()
	{
		resolvingAttempt = false;
		if ((Object)(object)highlighter != (Object)null)
		{
			highlighter.Clear();
		}
		DestroyTriggers();
	}

	private void OnDisable()
	{
		resolvingAttempt = false;
		DestroyTriggers();
	}

	private void OnDestroy()
	{
		Clear();
	}
}
internal class DoorAudioController : MonoBehaviour
{
	private DoorLock door;

	private AudioSource source;

	private AudioClip pickingClip;

	private AudioClip unlockClip;

	private AudioClip failClip;

	public void Init(DoorLock targetDoor)
	{
		door = targetDoor;
		source = ((Component)this).gameObject.GetComponent<AudioSource>();
		if ((Object)(object)source == (Object)null)
		{
			source = ((Component)this).gameObject.AddComponent<AudioSource>();
		}
		source.playOnAwake = false;
		source.loop = false;
		source.spatialBlend = 1f;
		source.rolloffMode = (AudioRolloffMode)1;
		source.minDistance = 1f;
		source.maxDistance = 18f;
		source.dopplerLevel = 0f;
		source.spatialize = false;
		pickingClip = AudioUtil.GetAudioClip(door, new string[3] { "pickingLockSFX", "pickLockSFX", "lockpickSFX" });
		unlockClip = AudioUtil.GetAudioClip(door, new string[3] { "unlockSFX", "unlockDoorSFX", "doorUnlockSFX" });
		failClip = AudioUtil.GetAudioClip(door, new string[3] { "doorLockSFX", "lockedDoorSFX", "lockSFX" });
	}

	public void StartLockpickLoop()
	{
		if (!((Object)(object)source == (Object)null) && !((Object)(object)pickingClip == (Object)null))
		{
			float volume = ((DoorLockpickPlus.LockpickSoundVolume != null) ? Mathf.Clamp01(DoorLockpickPlus.LockpickSoundVolume.Value) : 0.75f);
			if (source.isPlaying && (Object)(object)source.clip == (Object)(object)pickingClip && source.loop)
			{
				source.volume = volume;
				return;
			}
			source.Stop();
			source.clip = pickingClip;
			source.loop = true;
			source.volume = volume;
			source.Play();
		}
	}

	public void StopLockpickLoop()
	{
		if (!((Object)(object)source == (Object)null) && (Object)(object)source.clip == (Object)(object)pickingClip && source.loop)
		{
			source.Stop();
			source.loop = false;
			source.clip = null;
		}
	}

	public void PlayUnlockSoundOnce()
	{
		StopLockpickLoop();
		PlayOneShotClean(unlockClip);
	}

	public void PlayFailSoundOnce()
	{
		StopLockpickLoop();
		PlayOneShotClean(failClip);
	}

	private void PlayOneShotClean(AudioClip clip)
	{
		if (!((Object)(object)source == (Object)null) && !((Object)(object)clip == (Object)null))
		{
			float num = ((DoorLockpickPlus.LockpickSoundVolume != null) ? Mathf.Clamp01(DoorLockpickPlus.LockpickSoundVolume.Value) : 0.75f);
			source.loop = false;
			source.clip = null;
			source.Stop();
			source.PlayOneShot(clip, num);
		}
	}

	private void OnDestroy()
	{
		if ((Object)(object)source != (Object)null)
		{
			source.Stop();
		}
	}
}
internal class DoorVisualHighlighter : MonoBehaviour
{
	private readonly List<Renderer> renderers = new List<Renderer>();

	private readonly Dictionary<Renderer, MaterialPropertyBlock> blocks = new Dictionary<Renderer, MaterialPropertyBlock>();

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

	private readonly List<Material> overlayMaterials = new List<Material>();

	private GameObject lightObject;

	private Light lightSource;

	private bool isBigDoor;

	public void Init(GameObject root, Bounds focusBounds, bool bigDoor)
	{
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		isBigDoor = bigDoor;
		CacheRenderers(root, focusBounds, bigDoor);
		CreateOverlayMeshes();
		CreateLight();
		if (DoorLockpickPlus.Log != null)
		{
			string text = (((Object)(object)root != (Object)null) ? ((Object)root).name : "null");
			DoorLockpickPlus.Log.LogInfo((object)("DoorLockpickPlus visual renderers for " + text + ": " + renderers.Count));
		}
	}

	private void CacheRenderers(GameObject root, Bounds focusBounds, bool bigDoor)
	{
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c7: 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_0124: Expected O, but got Unknown
		renderers.Clear();
		blocks.Clear();
		if ((Object)(object)root == (Object)null)
		{
			return;
		}
		List<Renderer> list = new List<Renderer>();
		CollectRendererCandidates(root.transform, focusBounds, bigDoor, list);
		if (!bigDoor && list.Count == 0 && (Object)(object)root.transform.parent != (Object)null)
		{
			CollectRendererCandidates(root.transform.parent, focusBounds, bigDoor, list);
		}
		if (!bigDoor && list.Count == 0 && (Object)(object)root.transform.parent != (Object)null && (Object)(object)root.transform.parent.parent != (Object)null)
		{
			CollectRendererCandidates(root.transform.parent.parent, focusBounds, bigDoor, list);
		}
		for (int i = 0; i < list.Count; i++)
		{
			Renderer val = list[i];
			if (!((Object)(object)val == (Object)null) && !renderers.Contains(val))
			{
				renderers.Add(val);
				blocks[val] = new MaterialPropertyBlock();
			}
		}
	}

	private void CollectRendererCandidates(Transform root, Bounds focusBounds, bool bigDoor, List<Renderer> output)
	{
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_0088: Unknown result type (might be due to invalid IL or missing references)
		//IL_008d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0091: 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)
		if ((Object)(object)root == (Object)null || output == null)
		{
			return;
		}
		Renderer[] componentsInChildren = ((Component)root).GetComponentsInChildren<Renderer>(true);
		Bounds val = focusBounds;
		((Bounds)(ref val)).Expand(bigDoor ? 4f : 5f);
		Renderer[] array = componentsInChildren;
		foreach (Renderer val2 in array)
		{
			if (!RendererUtil.IsVisibleDoorRenderer(val2, bigDoor))
			{
				continue;
			}
			if (!bigDoor && !((Bounds)(ref val)).Intersects(val2.bounds))
			{
				Bounds bounds = val2.bounds;
				float num = Vector3.Distance(((Bounds)(ref bounds)).center, ((Bounds)(ref focusBounds)).center);
				if (num > 5.5f)
				{
					continue;
				}
			}
			if (!output.Contains(val2))
			{
				output.Add(val2);
			}
		}
	}

	private void CreateOverlayMeshes()
	{
		foreach (Renderer renderer in renderers)
		{
			if ((Object)(object)renderer == (Object)null)
			{
				continue;
			}
			MeshFilter component = ((Component)renderer).GetComponent<MeshFilter>();
			if ((Object)(object)component != (Object)null && (Object)(object)component.sharedMesh != (Object)null)
			{
				CreateMeshOverlay(renderer, component.sharedMesh);
				continue;
			}
			SkinnedMeshRenderer val = (SkinnedMeshRenderer)(object)((renderer is SkinnedMeshRenderer) ? renderer : null);
			if ((Object)(object)val != (Object)null && (Object)(object)val.sharedMesh != (Object)null)
			{
				CreateSkinnedMeshOverlay(val);
			}
		}
	}

	private void CreateMeshOverlay(Renderer originalRenderer, Mesh mesh)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Expected O, but got Unknown
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: 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_0085: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject("DoorLockpickPlus_OverlayMesh");
		val.transform.SetParent(((Component)originalRenderer).transform, false);
		val.transform.localPosition = Vector3.zero;
		val.transform.localRotation = Quaternion.identity;
		val.transform.localScale = Vector3.one * 1.006f;
		val.layer = ((Component)originalRenderer).gameObject.layer;
		MeshFilter val2 = val.AddComponent<MeshFilter>();
		val2.sharedMesh = mesh;
		MeshRenderer val3 = val.AddComponent<MeshRenderer>();
		Material item = (((Renderer)val3).sharedMaterial = CreateOverlayMaterial(Color.clear));
		((Renderer)val3).shadowCastingMode = (ShadowCastingMode)0;
		((Renderer)val3).receiveShadows = false;
		((Renderer)val3).enabled = false;
		overlayObjects.Add(val);
		overlayMaterials.Add(item);
	}

	private void CreateSkinnedMeshOverlay(SkinnedMeshRenderer originalRenderer)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Expected O, but got Unknown
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: 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_009d: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject("DoorLockpickPlus_OverlaySkinnedMesh");
		val.transform.SetParent(((Component)originalRenderer).transform, false);
		val.transform.localPosition = Vector3.zero;
		val.transform.localRotation = Quaternion.identity;
		val.transform.localScale = Vector3.one * 1.006f;
		val.layer = ((Component)originalRenderer).gameObject.layer;
		SkinnedMeshRenderer val2 = val.AddComponent<SkinnedMeshRenderer>();
		val2.sharedMesh = originalRenderer.sharedMesh;
		val2.bones = originalRenderer.bones;
		val2.rootBone = originalRenderer.rootBone;
		Material item = (((Renderer)val2).sharedMaterial = CreateOverlayMaterial(Color.clear));
		((Renderer)val2).shadowCastingMode = (ShadowCastingMode)0;
		((Renderer)val2).receiveShadows = false;
		((Renderer)val2).enabled = false;
		overlayObjects.Add(val);
		overlayMaterials.Add(item);
	}

	private Material CreateOverlayMaterial(Color color)
	{
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Expected O, but got Unknown
		//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
		Shader val = Shader.Find("Sprites/Default");
		if ((Object)(object)val == (Object)null)
		{
			val = Shader.Find("Particles/Standard Unlit");
		}
		if ((Object)(object)val == (Object)null)
		{
			val = Shader.Find("Unlit/Color");
		}
		if ((Object)(object)val == (Object)null)
		{
			val = Shader.Find("Standard");
		}
		Material val2 = new Material(val);
		((Object)val2).name = "DoorLockpickPlus_OverlayMaterial";
		val2.renderQueue = 3100;
		if (val2.HasProperty("_SrcBlend"))
		{
			val2.SetInt("_SrcBlend", 5);
		}
		if (val2.HasProperty("_DstBlend"))
		{
			val2.SetInt("_DstBlend", 10);
		}
		if (val2.HasProperty("_ZWrite"))
		{
			val2.SetInt("_ZWrite", 0);
		}
		if (val2.HasProperty("_Cull"))
		{
			val2.SetInt("_Cull", 0);
		}
		SetMaterialColor(val2, color, 1f);
		return val2;
	}

	private void CreateLight()
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Expected O, but got Unknown
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		lightObject = new GameObject("DoorLockpickPlus_HighlightLight");
		lightObject.transform.SetParent(((Component)this).transform, false);
		lightObject.transform.localPosition = Vector3.zero;
		lightSource = lightObject.AddComponent<Light>();
		lightSource.type = (LightType)2;
		lightSource.range = 4f;
		lightSource.intensity = 0f;
		lightSource.shadows = (LightShadows)0;
		lightSource.renderMode = (LightRenderMode)1;
		((Behaviour)lightSource).enabled = false;
	}

	public void Apply(Color color, float strength, bool enableLight, float multiplier)
	{
		//IL_0091: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_009b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a0: 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_00a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_0103: Unknown result type (might be due to invalid IL or missing references)
		//IL_0112: Unknown result type (might be due to invalid IL or missing references)
		//IL_0121: 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_0160: Unknown result type (might be due to invalid IL or missing references)
		//IL_0161: Unknown result type (might be due to invalid IL or missing references)
		//IL_0234: Unknown result type (might be due to invalid IL or missing references)
		//IL_0239: Unknown result type (might be due to invalid IL or missing references)
		//IL_0248: Unknown result type (might be due to invalid IL or missing references)
		//IL_0259: Unknown result type (might be due to invalid IL or missing references)
		//IL_0268: Unknown result type (might be due to invalid IL or missing references)
		//IL_026d: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
		float num = ((DoorLockpickPlus.DoorTintStrength != null) ? Mathf.Clamp01(DoorLockpickPlus.DoorTintStrength.Value) : 0.55f);
		float num2 = ((DoorLockpickPlus.DoorOverlayAlpha != null) ? Mathf.Clamp01(DoorLockpickPlus.DoorOverlayAlpha.Value) : 0.18f);
		float num3 = ((DoorLockpickPlus.DoorEmissionStrength != null) ? Mathf.Max(0f, DoorLockpickPlus.DoorEmissionStrength.Value) : 1.15f);
		float num4 = ((DoorLockpickPlus.DoorLightStrength != null) ? Mathf.Max(0f, DoorLockpickPlus.DoorLightStrength.Value) : 0.55f);
		float num5 = Mathf.Max(0f, multiplier);
		Color val = Color.Lerp(Color.white, color, num * num5);
		Color val2 = color * num3 * strength * num5;
		foreach (Renderer renderer in renderers)
		{
			if (!((Object)(object)renderer == (Object)null))
			{
				MaterialPropertyBlock val3 = blocks[renderer];
				renderer.GetPropertyBlock(val3);
				val3.SetColor("_Color", val);
				val3.SetColor("_BaseColor", val);
				val3.SetColor("_EmissionColor", val2);
				val3.SetColor("_EmissiveColor", val2);
				renderer.SetPropertyBlock(val3);
			}
		}
		Color color2 = color;
		color2.a = num2 * num5;
		for (int i = 0; i < overlayObjects.Count; i++)
		{
			GameObject val4 = overlayObjects[i];
			if (!((Object)(object)val4 == (Object)null))
			{
				Renderer component = val4.GetComponent<Renderer>();
				if ((Object)(object)component != (Object)null)
				{
					component.enabled = true;
				}
				if (i < overlayMaterials.Count && (Object)(object)overlayMaterials[i] != (Object)null)
				{
					SetMaterialColor(overlayMaterials[i], color2, num5);
				}
			}
		}
		if ((Object)(object)lightSource != (Object)null)
		{
			Bounds acceptedRendererBounds = GetAcceptedRendererBounds();
			((Component)lightSource).transform.position = ((Bounds)(ref acceptedRendererBounds)).center;
			lightSource.color = color;
			Light obj = lightSource;
			Vector3 extents = ((Bounds)(ref acceptedRendererBounds)).extents;
			obj.range = Mathf.Clamp(((Vector3)(ref extents)).magnitude * (isBigDoor ? 0.75f : 1.05f), 1.5f, isBigDoor ? 5.5f : 7f);
			lightSource.intensity = (enableLight ? Mathf.Clamp(num4 * strength * num5, 0f, isBigDoor ? 1.2f : 2.5f) : 0f);
			((Behaviour)lightSource).enabled = enableLight && renderers.Count > 0;
		}
	}

	public void Clear()
	{
		foreach (Renderer renderer in renderers)
		{
			if (!((Object)(object)renderer == (Object)null))
			{
				renderer.SetPropertyBlock((MaterialPropertyBlock)null);
			}
		}
		for (int i = 0; i < overlayObjects.Count; i++)
		{
			GameObject val = overlayObjects[i];
			if (!((Object)(object)val == (Object)null))
			{
				Renderer component = val.GetComponent<Renderer>();
				if ((Object)(object)component != (Object)null)
				{
					component.enabled = false;
				}
			}
		}
		if ((Object)(object)lightSource != (Object)null)
		{
			((Behaviour)lightSource).enabled = false;
			lightSource.intensity = 0f;
		}
	}

	private Bounds GetAcceptedRendererBounds()
	{
		//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_007c: 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_0081: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_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)
		Bounds bounds = default(Bounds);
		((Bounds)(ref bounds))..ctor(((Component)this).transform.position, Vector3.one);
		bool flag = false;
		for (int i = 0; i < renderers.Count; i++)
		{
			Renderer val = renderers[i];
			if (!((Object)(object)val == (Object)null))
			{
				if (!flag)
				{
					bounds = val.bounds;
					flag = true;
				}
				else
				{
					((Bounds)(ref bounds)).Encapsulate(val.bounds);
				}
			}
		}
		return bounds;
	}

	private void SetMaterialColor(Material mat, Color color, float multiplier)
	{
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0061: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)mat == (Object)null))
		{
			if (mat.HasProperty("_Color"))
			{
				mat.SetColor("_Color", color);
			}
			if (mat.HasProperty("_BaseColor"))
			{
				mat.SetColor("_BaseColor", color);
			}
			if (mat.HasProperty("_EmissionColor"))
			{
				mat.SetColor("_EmissionColor", color * (1f + multiplier));
			}
		}
	}

	private void OnDestroy()
	{
		Clear();
		for (int i = 0; i < overlayObjects.Count; i++)
		{
			if ((Object)(object)overlayObjects[i] != (Object)null)
			{
				Object.Destroy((Object)(object)overlayObjects[i]);
			}
		}
		overlayObjects.Clear();
		for (int j = 0; j < overlayMaterials.Count; j++)
		{
			if ((Object)(object)overlayMaterials[j] != (Object)null)
			{
				Object.Destroy((Object)(object)overlayMaterials[j]);
			}
		}
		overlayMaterials.Clear();
		if ((Object)(object)lightObject != (Object)null)
		{
			Object.Destroy((Object)(object)lightObject);
			lightObject = null;
		}
	}
}
internal class TriggerSnapshot
{
	private readonly string hoverTip;

	private readonly string holdTip;

	private readonly bool interactable;

	private readonly bool holdInteraction;

	private readonly float timeToHold;

	private readonly float timeToHoldSpeedMultiplier;

	private readonly bool oneHandedItemAllowed;

	private readonly bool twoHandedItemAllowed;

	private readonly bool interactCooldown;

	private readonly float cooldownTime;

	private readonly bool triggerOnce;

	public TriggerSnapshot(InteractTrigger trigger)
	{
		hoverTip = trigger.hoverTip;
		holdTip = trigger.holdTip;
		interactable = trigger.interactable;
		holdInteraction = trigger.holdInteraction;
		timeToHold = trigger.timeToHold;
		timeToHoldSpeedMultiplier = trigger.timeToHoldSpeedMultiplier;
		oneHandedItemAllowed = trigger.oneHandedItemAllowed;
		twoHandedItemAllowed = trigger.twoHandedItemAllowed;
		interactCooldown = trigger.interactCooldown;
		cooldownTime = trigger.cooldownTime;
		triggerOnce = trigger.triggerOnce;
	}

	public void Restore(InteractTrigger trigger)
	{
		trigger.hoverTip = hoverTip;
		trigger.holdTip = holdTip;
		trigger.interactable = interactable;
		trigger.holdInteraction = holdInteraction;
		trigger.timeToHold = timeToHold;
		trigger.timeToHoldSpeedMultiplier = timeToHoldSpeedMultiplier;
		trigger.oneHandedItemAllowed = oneHandedItemAllowed;
		trigger.twoHandedItemAllowed = twoHandedItemAllowed;
		trigger.interactCooldown = interactCooldown;
		trigger.cooldownTime = cooldownTime;
		trigger.triggerOnce = triggerOnce;
	}
}
internal static class InteractTriggerUtil
{
	private static readonly FieldInfo onInteractField = AccessTools.Field(typeof(InteractTrigger), "onInteract");

	private static readonly FieldInfo onInteractEarlyField = AccessTools.Field(typeof(InteractTrigger), "onInteractEarly");

	private static readonly FieldInfo onStopInteractField = AccessTools.Field(typeof(InteractTrigger), "onStopInteract");

	private static readonly FieldInfo holdingInteractEventField = AccessTools.Field(typeof(InteractTrigger), "holdingInteractEvent");

	private static readonly FieldInfo onCancelAnimationField = AccessTools.Field(typeof(InteractTrigger), "onCancelAnimation");

	public static void MakeGameObjectARealInteractTrigger(GameObject obj)
	{
		if (!((Object)(object)obj == (Object)null))
		{
			TrySetTag(obj, "InteractTrigger");
			obj.layer = LayerUtil.InteractableLayer();
			Collider component = obj.GetComponent<Collider>();
			if ((Object)(object)component != (Object)null)
			{
				component.isTrigger = true;
			}
			Renderer component2 = obj.GetComponent<Renderer>();
			if ((Object)(object)component2 != (Object)null)
			{
				component2.enabled = false;
			}
		}
	}

	private static void TrySetTag(GameObject obj, string tag)
	{
		try
		{
			obj.tag = tag;
		}
		catch
		{
		}
	}

	public static void ConfigureBaseTrigger(InteractTrigger trigger)
	{
		if (!((Object)(object)trigger == (Object)null))
		{
			MakeGameObjectARealInteractTrigger(((Component)trigger).gameObject);
			trigger.interactable = true;
			trigger.oneHandedItemAllowed = true;
			trigger.twoHandedItemAllowed = true;
			trigger.holdInteraction = true;
			trigger.timeToHoldSpeedMultiplier = 1f;
			trigger.interactCooldown = true;
			trigger.cooldownTime = 0.5f;
			trigger.triggerOnce = false;
			trigger.stopAnimationString = "SA_stopAnimation";
			trigger.animationWaitTime = 2f;
			trigger.lockPlayerPosition = true;
			trigger.disableTriggerMesh = true;
			EnsureEventObject(trigger, onInteractField);
			EnsureEventObject(trigger, onInteractEarlyField);
			EnsureEventObject(trigger, onStopInteractField);
			EnsureEventObject(trigger, holdingInteractEventField);
			EnsureEventObject(trigger, onCancelAnimationField);
			CopyIconFromScene(trigger);
		}
	}

	public static void CopyIconFromTriggers(InteractTrigger target, List<InteractTrigger> templates)
	{
		if ((Object)(object)target == (Object)null)
		{
			return;
		}
		if (templates != null)
		{
			for (int i = 0; i < templates.Count; i++)
			{
				InteractTrigger val = templates[i];
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val == (Object)(object)target))
				{
					if ((Object)(object)val.hoverIcon != (Object)null)
					{
						target.hoverIcon = val.hoverIcon;
					}
					if ((Object)(object)val.disabledHoverIcon != (Object)null)
					{
						target.disabledHoverIcon = val.disabledHoverIcon;
					}
					if ((Object)(object)target.hoverIcon != (Object)null)
					{
						return;
					}
				}
			}
		}
		CopyIconFromScene(target);
	}

	public static void CopyIconFromScene(InteractTrigger target)
	{
		if ((Object)(object)target == (Object)null || (Object)(object)target.hoverIcon != (Object)null)
		{
			return;
		}
		InteractTrigger[] array = Object.FindObjectsOfType<InteractTrigger>();
		foreach (InteractTrigger val in array)
		{
			if (!((Object)(object)val == (Object)null) && !((Object)(object)val == (Object)(object)target) && (Object)(object)val.hoverIcon != (Object)null)
			{
				target.hoverIcon = val.hoverIcon;
				target.disabledHoverIcon = (((Object)(object)val.disabledHoverIcon != (Object)null) ? val.disabledHoverIcon : val.hoverIcon);
				break;
			}
		}
	}

	private static object EnsureEventObject(InteractTrigger trigger, FieldInfo field)
	{
		try
		{
			if ((Object)(object)trigger == (Object)null || field == null)
			{
				return null;
			}
			object obj = field.GetValue(trigger);
			if (obj == null)
			{
				obj = Activator.CreateInstance(field.FieldType);
				field.SetValue(trigger, obj);
			}
			return obj;
		}
		catch
		{
			return null;
		}
	}

	public static void AddInteractListener(InteractTrigger trigger, Action<PlayerControllerB> callback)
	{
		try
		{
			if ((Object)(object)trigger == (Object)null || callback == null || onInteractField == null)
			{
				return;
			}
			object obj = EnsureEventObject(trigger, onInteractField);
			if (obj == null)
			{
				return;
			}
			UnityAction<PlayerControllerB> val = callback.Invoke;
			MethodInfo method = obj.GetType().GetMethod("AddListener", new Type[1] { typeof(UnityAction<PlayerControllerB>) });
			if (method != null)
			{
				method.Invoke(obj, new object[1] { val });
				return;
			}
			MethodInfo[] methods = obj.GetType().GetMethods();
			foreach (MethodInfo methodInfo in methods)
			{
				if (!(methodInfo.Name != "AddListener"))
				{
					ParameterInfo[] parameters = methodInfo.GetParameters();
					if (parameters.Length == 1)
					{
						methodInfo.Invoke(obj, new object[1] { val });
						break;
					}
				}
			}
		}
		catch (Exception ex)
		{
			if (DoorLockpickPlus.Log != null)
			{
				DoorLockpickPlus.Log.LogWarning((object)("Failed to add InteractTrigger listener: " + ex.Message));
			}
		}
	}
}
internal static class BigDoorUtil
{
	public static bool IsProbablyBigDoor(TerminalAccessibleObject obj)
	{
		if ((Object)(object)obj == (Object)null)
		{
			return false;
		}
		if (obj.isBigDoor)
		{
			return true;
		}
		string text = ((Object)((Component)obj).gameObject).name.ToLowerInvariant();
		if (text.Contains("bigdoor") || text.Contains("big door"))
		{
			return true;
		}
		Transform parent = ((Component)obj).transform.parent;
		while ((Object)(object)parent != (Object)null)
		{
			string text2 = ((Object)parent).name.ToLowerInvariant();
			if (text2.Contains("bigdoor") || text2.Contains("big door"))
			{
				return true;
			}
			parent = parent.parent;
		}
		return false;
	}

	public static bool IsOpen(TerminalAccessibleObject obj)
	{
		if ((Object)(object)obj == (Object)null)
		{
			return false;
		}
		return ReflectionUtil.GetBoolFieldExact(obj, "isDoorOpen");
	}

	public static string GetObjectCode(TerminalAccessibleObject obj)
	{
		if ((Object)(object)obj == (Object)null)
		{
			return "";
		}
		try
		{
			if (!string.IsNullOrEmpty(obj.objectCode))
			{
				return obj.objectCode;
			}
		}
		catch
		{
		}
		return "";
	}

	public static void ClearCooldown(TerminalAccessibleObject obj)
	{
		if (!((Object)(object)obj == (Object)null))
		{
			ReflectionUtil.SetBoolFieldExact(obj, "inCooldown", value: false);
			ReflectionUtil.SetFloatFieldExact(obj, "currentCooldownTimer", 0f);
		}
	}

	public static void SendTerminalCommand(TerminalAccessibleObject obj)
	{
		if (!((Object)(object)obj == (Object)null))
		{
			ClearCooldown(obj);
			ReflectionUtil.CallNoArgExact(obj, "CallFunctionFromTerminal");
		}
	}

	public static void ForceSetOpen(TerminalAccessibleObject obj, bool open)
	{
		if (!((Object)(object)obj == (Object)null))
		{
			ClearCooldown(obj);
			ReflectionUtil.SetBoolFieldExact(obj, "isDoorOpen", open);
			ReflectionUtil.CallBoolArgExact(obj, "SetDoorOpen", open);
			ReflectionUtil.CallBoolArgExact(obj, "SetDoorLocalClient", open);
			ReflectionUtil.CallBoolArgExact(obj, "SetDoorOpenClientRpc", open);
			ReflectionUtil.CallBoolArgExact(obj, "SetDoorOpenServerRpc", open);
			ReflectionUtil.SetBoolFieldExact(obj, "isDoorOpen", open);
		}
	}
}
internal static class AudioUtil
{
	public static AudioClip GetAudioClip(object instance, string[] fieldNames)
	{
		if (instance == null || fieldNames == null)
		{
			return null;
		}
		for (int i = 0; i < fieldNames.Length; i++)
		{
			AudioClip fieldValueExact = ReflectionUtil.GetFieldValueExact<AudioClip>(instance, fieldNames[i]);
			if ((Object)(object)fieldValueExact != (Object)null)
			{
				return fieldValueExact;
			}
		}
		return null;
	}
}
internal static class RendererUtil
{
	public static bool IsVisibleDoorRenderer(Renderer renderer, bool bigDoor)
	{
		//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_00d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)renderer == (Object)null)
		{
			return false;
		}
		if (!renderer.enabled || !((Component)renderer).gameObject.activeInHierarchy)
		{
			return false;
		}
		string lowerName = ((Object)((Component)renderer).gameObject).name.ToLowerInvariant();
		string text = GetPath(((Component)renderer).transform).ToLowerInvariant();
		string text2 = ((object)renderer).GetType().Name.ToLowerInvariant();
		if (text2.Contains("particle") || text2.Contains("line") || text2.Contains("trail"))
		{
			return false;
		}
		if (ShouldSkipVisualName(lowerName) || ShouldSkipVisualName(text))
		{
			return false;
		}
		Bounds bounds = renderer.bounds;
		Vector3 size = ((Bounds)(ref bounds)).size;
		if (((Vector3)(ref size)).sqrMagnitude <= 0.0001f)
		{
			return false;
		}
		MeshFilter component = ((Component)renderer).GetComponent<MeshFilter>();
		SkinnedMeshRenderer val = (SkinnedMeshRenderer)(object)((renderer is SkinnedMeshRenderer) ? renderer : null);
		if (((Object)(object)component == (Object)null || (Object)(object)component.sharedMesh == (Object)null) && ((Object)(object)val == (Object)null || (Object)(object)val.sharedMesh == (Object)null))
		{
			return false;
		}
		if (bigDoor && (text.Contains("doorcode") || text.Contains("map") || text.Contains("screen") || text.Contains("ui")))
		{
			return false;
		}
		return true;
	}

	private static bool ShouldSkipVisualName(string lowerName)
	{
		if (string.IsNullOrEmpty(lowerName))
		{
			return false;
		}
		return lowerName.Contains("trigger") || lowerName.Contains("collider") || lowerName.Contains("collision") || lowerName.Contains("hitbox") || lowerName.Contains("lockpickplus") || lowerName.Contains("interact") || lowerName.Contains("scan") || lowerName.Contains("node") || lowerName.Contains("radar") || lowerName.Contains("code") || lowerName.Contains("ui") || lowerName.Contains("audio") || lowerName.Contains("light") || lowerName.Contains("particle") || lowerName.Contains("spark") || lowerName.Contains("nav") || lowerName.Contains("bounds");
	}

	private static string GetPath(Transform transform)
	{
		if ((Object)(object)transform == (Object)null)
		{
			return "";
		}
		string text = ((Object)transform).name;
		Transform parent = transform.parent;
		int num = 0;
		while ((Object)(object)parent != (Object)null && num < 12)
		{
			text = ((Object)parent).name + "/" + text;
			parent = parent.parent;
			num++;
		}
		return text;
	}
}
internal static class LayerUtil
{
	public static int InteractableLayer()
	{
		int num = LayerMask.NameToLayer("InteractableObject");
		if (num >= 0)
		{
			return num;
		}
		num = LayerMask.NameToLayer("Interactable");
		if (num >= 0)
		{
			return num;
		}
		return 0;
	}
}
internal static class BoundsUtil
{
	public static Bounds GetBounds(GameObject root)
	{
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0175: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0158: Unknown result type (might be due to invalid IL or missing references)
		//IL_015d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0167: Unknown result type (might be due to invalid IL or missing references)
		//IL_016c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0171: Unknown result type (might be due to invalid IL or missing references)
		//IL_014d: Unknown result type (might be due to invalid IL or missing references)
		//IL_014e: Unknown result type (might be due to invalid IL or missing references)
		//IL_012a: Unknown result type (might be due to invalid IL or missing references)
		//IL_011a: Unknown result type (might be due to invalid IL or missing references)
		//IL_011f: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)root == (Object)null)
		{
			return new Bounds(Vector3.zero, Vector3.one);
		}
		Bounds bounds = default(Bounds);
		((Bounds)(ref bounds))..ctor(root.transform.position, Vector3.one);
		bool flag = false;
		Renderer[] componentsInChildren = root.GetComponentsInChildren<Renderer>(true);
		Renderer[] array = componentsInChildren;
		foreach (Renderer val in array)
		{
			if (RendererUtil.IsVisibleDoorRenderer(val, bigDoor: true) || RendererUtil.IsVisibleDoorRenderer(val, bigDoor: false))
			{
				if (!flag)
				{
					bounds = val.bounds;
					flag = true;
				}
				else
				{
					((Bounds)(ref bounds)).Encapsulate(val.bounds);
				}
			}
		}
		if (flag)
		{
			return bounds;
		}
		Collider[] componentsInChildren2 = root.GetComponentsInChildren<Collider>(true);
		Collider[] array2 = componentsInChildren2;
		foreach (Collider val2 in array2)
		{
			if ((Object)(object)val2 == (Object)null)
			{
				continue;
			}
			string lowerName = ((Object)((Component)val2).gameObject).name.ToLowerInvariant();
			if (!ShouldSkipBoundsName(lowerName))
			{
				if (!flag)
				{
					bounds = val2.bounds;
					flag = true;
				}
				else
				{
					((Bounds)(ref bounds)).Encapsulate(val2.bounds);
				}
			}
		}
		if (flag)
		{
			return bounds;
		}
		return new Bounds(root.transform.position, Vector3.one * 3f);
	}

	public static List<Bounds> GetIndividualVisualBounds(GameObject root, bool bigDoor)
	{
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_0074: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
		List<Bounds> list = new List<Bounds>();
		if ((Object)(object)root == (Object)null)
		{
			return list;
		}
		Renderer[] componentsInChildren = root.GetComponentsInChildren<Renderer>(true);
		Renderer[] array = componentsInChildren;
		Vector3 size;
		foreach (Renderer val in array)
		{
			if (RendererUtil.IsVisibleDoorRenderer(val, bigDoor))
			{
				Bounds bounds = val.bounds;
				size = ((Bounds)(ref bounds)).size;
				if (!(((Vector3)(ref size)).sqrMagnitude <= 0.0001f))
				{
					list.Add(bounds);
				}
			}
		}
		if (list.Count == 0)
		{
			Bounds bounds2 = GetBounds(root);
			size = ((Bounds)(ref bounds2)).size;
			if (((Vector3)(ref size)).sqrMagnitude > 0.0001f)
			{
				list.Add(bounds2);
			}
		}
		return list;
	}

	public static void EncapsulateTransformBounds(Transform transform, ref Bounds bounds, ref bool hasBounds)
	{
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: 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)
		if ((Object)(object)transform == (Object)null)
		{
			return;
		}
		Collider component = ((Component)transform).GetComponent<Collider>();
		if ((Object)(object)component != (Object)null)
		{
			if (!hasBounds)
			{
				bounds = component.bounds;
				hasBounds = true;
			}
			else
			{
				((Bounds)(ref bounds)).Encapsulate(component.bounds);
			}
			return;
		}
		Renderer component2 = ((Component)transform).GetComponent<Renderer>();
		if ((Object)(object)component2 != (Object)null)
		{
			if (!hasBounds)
			{
				bounds = component2.bounds;
				hasBounds = true;
			}
			else
			{
				((Bounds)(ref bounds)).Encapsulate(component2.bounds);
			}
		}
	}

	private static bool ShouldSkipBoundsName(string lowerName)
	{
		if (string.IsNullOrEmpty(lowerName))
		{
			return false;
		}
		return lowerName.Contains("trigger") || lowerName.Contains("lockpickplus") || lowerName.Contains("interact") || lowerName.Contains("scan") || lowerName.Contains("node") || lowerName.Contains("ui") || lowerName.Contains("audio") || lowerName.Contains("light");
	}
}
internal static class ReflectionUtil
{
	public static T GetFieldValueExact<T>(object instance, string fieldName) where T : class
	{
		try
		{
			if (instance == null)
			{
				return null;
			}
			FieldInfo field = instance.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field == null)
			{
				return null;
			}
			object value = field.GetValue(instance);
			return value as T;
		}
		catch
		{
			return null;
		}
	}

	public static bool GetBoolFieldExact(object instance, string fieldName)
	{
		try
		{
			if (instance == null)
			{
				return false;
			}
			FieldInfo field = instance.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field == null || field.FieldType != typeof(bool))
			{
				return false;
			}
			object value = field.GetValue(instance);
			if (value is bool)
			{
				return (bool)value;
			}
		}
		catch
		{
		}
		return false;
	}

	public static void SetBoolFieldExact(object instance, string fieldName, bool value)
	{
		try
		{
			if (instance != null)
			{
				FieldInfo field = instance.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (!(field == null) && !(field.FieldType != typeof(bool)))
				{
					field.SetValue(instance, value);
				}
			}
		}
		catch
		{
		}
	}

	public static void SetFloatFieldExact(object instance, string fieldName, float value)
	{
		try
		{
			if (instance != null)
			{
				FieldInfo field = instance.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (!(field == null) && !(field.FieldType != typeof(float)))
				{
					field.SetValue(instance, value);
				}
			}
		}
		catch
		{
		}
	}

	public static bool CallNoArgExact(object instance, string methodName)
	{
		try
		{
			if (instance == null)
			{
				return false;
			}
			MethodInfo method = instance.GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (method == null || method.GetParameters().Length != 0)
			{
				return false;
			}
			method.Invoke(instance, null);
			return true;
		}
		catch
		{
			return false;
		}
	}

	public static bool CallBoolArgExact(object instance, string methodName, bool value)
	{
		try
		{
			if (instance == null)
			{
				return false;
			}
			MethodInfo method = instance.GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (method == null)
			{
				return false;
			}
			ParameterInfo[] parameters = method.GetParameters();
			if (parameters.Length != 1 || parameters[0].ParameterType != typeof(bool))
			{
				return false;
			}
			method.Invoke(instance, new object[1] { value });
			return true;
		}
		catch
		{
			return false;
		}
	}
}

plugins/CChanges/FacilityStartTeleport.dll

Decompiled 8 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("ScrapVisbility")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ScrapVisbility")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("8a6853bd-bdc9-4741-95c7-5aa2c8c6a6f9")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace FacilityStartTeleport;

[BepInPlugin("YourFurnace.FacilityStartTeleport", "FacilityStartTeleport", "1.2.5")]
public class FacilityStartTeleport : BaseUnityPlugin
{
	[CompilerGenerated]
	private sealed class <TryVanillaPickupAfterSpawn>d__84 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public PlayerControllerB player;

		public GrabbableObject grabbable;

		public FacilityStartTeleport <>4__this;

		private bool <called>5__1;

		object IEnumerator<object>.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		object IEnumerator.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		[DebuggerHidden]
		public <TryVanillaPickupAfterSpawn>d__84(int <>1__state)
		{
			this.<>1__state = <>1__state;
		}

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Expected O, but got Unknown
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				<>2__current = (object)new WaitForSeconds(0.25f);
				<>1__state = 1;
				return true;
			case 1:
				<>1__state = -1;
				if ((Object)(object)player == (Object)null || (Object)(object)grabbable == (Object)null)
				{
					return false;
				}
				ReflectionUtil.SetFieldObject(player, "currentlyGrabbingObject", grabbable);
				<called>5__1 = ReflectionUtil.CallNoArgMethod(player, "BeginGrabObject");
				if (!<called>5__1)
				{
					<>4__this.TryCallGrabObjectServerRpc(player, ((Component)grabbable).gameObject);
				}
				<>2__current = (object)new WaitForSeconds(0.35f);
				<>1__state = 2;
				return true;
			case 2:
				<>1__state = -1;
				if (!<>4__this.IsItemInPlayerInventory(player, grabbable))
				{
					<>4__this.SetupStartingItemAsRealDroppedItem(((Component)grabbable).gameObject, grabbable, grabbable.itemProperties, player);
					if (DebugLogging != null && DebugLogging.Value && Log != null)
					{
						Log.LogInfo((object)"Starting flashlight stayed as a normal pickup because vanilla auto-pickup did not claim it.");
					}
				}
				return false;
			}
		}

		bool IEnumerator.MoveNext()
		{
			//ILSpy generated this explicit interface implementation from .override directive in MoveNext
			return this.MoveNext();
		}

		[DebuggerHidden]
		void IEnumerator.Reset()
		{
			throw new NotSupportedException();
		}
	}

	private const string modGUID = "YourFurnace.FacilityStartTeleport";

	private const string modName = "FacilityStartTeleport";

	private const string modVersion = "1.2.5";

	internal static FacilityStartTeleport Instance;

	internal static ManualLogSource Log;

	internal static ConfigEntry<bool> EnableMod;

	internal static ConfigEntry<bool> SkipCompanyMoon;

	internal static ConfigEntry<bool> TeleportAllActivePlayers;

	internal static ConfigEntry<bool> DebugLogging;

	internal static ConfigEntry<float> TeleportDelayAfterLanding;

	internal static ConfigEntry<float> SpawnRadiusFromNode;

	internal static ConfigEntry<float> FloorRaycastHeight;

	internal static ConfigEntry<float> FloorRaycastDistance;

	internal static ConfigEntry<float> PlayerHeightOffset;

	internal static ConfigEntry<float> MaintainInsideStateSeconds;

	internal static ConfigEntry<bool> ApplyDynamicInsideAudioState;

	internal static ConfigEntry<float> InsideAudioSearchRadius;

	internal static ConfigEntry<bool> HideClockDuringInsideSpawn;

	internal static ConfigEntry<bool> RequireDungeonFinished;

	internal static ConfigEntry<bool> PreferInverseTeleporterLogic;

	internal static ConfigEntry<int> MaxSpawnAttempts;

	internal static ConfigEntry<float> CapsuleRadius;

	internal static ConfigEntry<float> CapsuleHeight;

	internal static ConfigEntry<float> MinimumWallClearance;

	internal static ConfigEntry<float> NavmeshSearchRadius;

	internal static ConfigEntry<float> MinimumCeilingClearance;

	internal static ConfigEntry<float> MaximumHeightDifferenceFromNearestNode;

	internal static ConfigEntry<bool> RejectPipeAndPropFloors;

	internal static ConfigEntry<float> MinimumDistanceFromEntrance;

	internal static ConfigEntry<bool> GiveFlashlightIfInventoryEmpty;

	internal static ConfigEntry<float> FlashlightGiveChance;

	internal static ConfigEntry<float> ProFlashlightChance;

	internal static ConfigEntry<string> NormalFlashlightNames;

	internal static ConfigEntry<string> ProFlashlightNames;

	internal static ConfigEntry<bool> EquipGivenFlashlight;

	private bool teleportedThisDay = false;

	private int lastRoundKey = int.MinValue;

	private float nextCheckTime = 0f;

	private float readyToTeleportTime = -1f;

	private float maintainInsideStateUntil = -1f;

	private readonly List<Transform> cachedInsideNodes = new List<Transform>();

	private float nextNodeRefreshTime = 0f;

	private void Awake()
	{
		Instance = this;
		Log = ((BaseUnityPlugin)this).Logger;
		EnableMod = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enable mod", true, "If true, players are moved into a random facility position at the start of a new day.");
		SkipCompanyMoon = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Skip Company moon", true, "If true, the mod will not run at The Company / Gordion.");
		TeleportAllActivePlayers = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Teleport all active players", true, "If true, attempts to teleport every active controlled player object. If false, only the local player is teleported. For multiplayer, all clients should have the mod installed.");
		DebugLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "Debug logging", true, "Logs when the mod finds nodes, validates spawn points, teleports players, and gives flashlights.");
		TeleportDelayAfterLanding = ((BaseUnityPlugin)this).Config.Bind<float>("Timing", "Teleport delay after landing", 6f, "Seconds to wait after the moon loads before teleporting players. This gives the facility and nodes time to spawn.");
		SpawnRadiusFromNode = ((BaseUnityPlugin)this).Config.Bind<float>("Spawning", "Spawn radius from inside node", 1.25f, "Random horizontal offset around the selected inside AI node. Lower is safer.");
		FloorRaycastHeight = ((BaseUnityPlugin)this).Config.Bind<float>("Spawning", "Floor raycast height", 1.35f, "How far above the candidate point the floor raycast starts. Keep this low so it does not hit ceiling pipes above the real floor.");
		FloorRaycastDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Spawning", "Floor raycast distance", 4f, "How far down the mod searches for a floor under the candidate point.");
		PlayerHeightOffset = ((BaseUnityPlugin)this).Config.Bind<float>("Spawning", "Player height offset", 0.75f, "How far above the detected floor the player is placed.");
		MaintainInsideStateSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Indoor State", "Maintain inside state seconds", 30f, "After teleporting, the mod briefly stabilizes isInsideFactory true. This is clamped to 3 seconds so exiting the facility does not break outside lighting.");
		ApplyDynamicInsideAudioState = ((BaseUnityPlugin)this).Config.Bind<bool>("Indoor State", "Apply dynamic inside audio state", true, "If true, the mod finds the map's active inside ambience AudioReverbTrigger and applies it to the local player after teleporting.");
		InsideAudioSearchRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Indoor State", "Inside audio search radius", 60f, "Used only as a tie breaker when choosing between multiple inside audio triggers. The mod does not rely on hardcoded map names.");
		HideClockDuringInsideSpawn = ((BaseUnityPlugin)this).Config.Bind<bool>("Indoor State", "Hide clock during inside spawn", true, "If true, asks HUDManager to hide the outside clock after the forced inside spawn. The actual fix is still the player inside state plus inside ambience trigger.");
		RequireDungeonFinished = ((BaseUnityPlugin)this).Config.Bind<bool>("Safe Spawning", "Require dungeon finished", true, "If true, the mod waits until the facility reports that dungeon generation finished before teleporting.");
		PreferInverseTeleporterLogic = ((BaseUnityPlugin)this).Config.Bind<bool>("Safe Spawning", "Prefer inverse teleporter logic", false, "If true, the mod tries to use the game's inverse teleporter position function first when an inverse teleporter exists. Default is false because some maps can return ceiling/pipe positions.");
		MaxSpawnAttempts = ((BaseUnityPlugin)this).Config.Bind<int>("Safe Spawning", "Max spawn attempts", 250, "How many random inside positions the mod tests before giving up for that player.");
		CapsuleRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Safe Spawning", "Player capsule radius", 0.34f, "Radius used when checking if the spawn point has enough space for the player.");
		CapsuleHeight = ((BaseUnityPlugin)this).Config.Bind<float>("Safe Spawning", "Player capsule height", 1.75f, "Height used when checking if the spawn point has enough space for the player.");
		MinimumWallClearance = ((BaseUnityPlugin)this).Config.Bind<float>("Safe Spawning", "Minimum wall clearance", 0.75f, "Horizontal clearance required around the player's chest. Raise this to avoid corners. Lower it if too many spawns fail.");
		NavmeshSearchRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Safe Spawning", "Navmesh search radius", 5f, "Radius used when asking RoundManager for a navmesh position around an inside AI node.");
		MinimumCeilingClearance = ((BaseUnityPlugin)this).Config.Bind<float>("Safe Spawning", "Minimum ceiling clearance", 2.15f, "Minimum clear vertical space above the spawn. This helps prevent spawning on pipes or ceiling props.");
		MaximumHeightDifferenceFromNearestNode = ((BaseUnityPlugin)this).Config.Bind<float>("Safe Spawning", "Maximum height difference from nearest node", 2.5f, "Rejects spawn points much higher or lower than the nearest inside AI node. This helps avoid ceiling pipes and out of bounds ledges.");
		RejectPipeAndPropFloors = ((BaseUnityPlugin)this).Config.Bind<bool>("Safe Spawning", "Reject pipe and prop floors", true, "Rejects floor hits on pipes, rails, sockets, props, vents, and similar non-floor objects.");
		MinimumDistanceFromEntrance = ((BaseUnityPlugin)this).Config.Bind<float>("Safe Spawning", "Minimum distance from entrances", 8f, "Rejects spawn points too close to main/fire exits. This helps prevent entrance triggers from repeatedly firing after the forced indoor spawn.");
		GiveFlashlightIfInventoryEmpty = ((BaseUnityPlugin)this).Config.Bind<bool>("Starting Flashlight", "Give flashlight if inventory empty", true, "If true, a player with no items has a chance to start with a normal flashlight or pro flashlight after being moved inside.");
		FlashlightGiveChance = ((BaseUnityPlugin)this).Config.Bind<float>("Starting Flashlight", "Chance to give flashlight", 1f, "Chance to give any flashlight when the player's inventory is empty. 1.0 means 100%.");
		ProFlashlightChance = ((BaseUnityPlugin)this).Config.Bind<float>("Starting Flashlight", "Chance flashlight is pro", 0.35f, "If a flashlight is given, this is the chance it is a pro flashlight. Normal flashlight is used if this roll fails.");
		NormalFlashlightNames = ((BaseUnityPlugin)this).Config.Bind<string>("Starting Flashlight", "Normal flashlight item names", "Flashlight", "Comma separated item names to search for normal flashlights.");
		ProFlashlightNames = ((BaseUnityPlugin)this).Config.Bind<string>("Starting Flashlight", "Pro flashlight item names", "Pro-flashlight,Pro flashlight,ProFlashlight", "Comma separated item names to search for pro flashlights.");
		EquipGivenFlashlight = ((BaseUnityPlugin)this).Config.Bind<bool>("Starting Flashlight", "Attempt vanilla pickup after spawn", false, "If true, the mod spawns the flashlight as a real network item and then tries to make vanilla pickup it. If false, it leaves the real flashlight at the player's feet. Safer default is false.");
		Log.LogInfo((object)"FacilityStartTeleport 1.2.5 loaded. Server-authoritative flashlight spawns, dynamic inside ambience state, and entrance-safe spawns enabled.");
	}

	private void Update()
	{
		if (EnableMod == null || !EnableMod.Value)
		{
			return;
		}
		if (Time.time < nextCheckTime)
		{
			MaintainInsideStateIfNeeded();
			return;
		}
		nextCheckTime = Time.time + 0.5f;
		MaintainInsideStateIfNeeded();
		if (!IsOnPlayableMoon())
		{
			teleportedThisDay = false;
			readyToTeleportTime = -1f;
			cachedInsideNodes.Clear();
			return;
		}
		int currentRoundKey = GetCurrentRoundKey();
		if (currentRoundKey != lastRoundKey)
		{
			lastRoundKey = currentRoundKey;
			teleportedThisDay = false;
			readyToTeleportTime = Time.time + Mathf.Max(0f, TeleportDelayAfterLanding.Value);
			cachedInsideNodes.Clear();
			nextNodeRefreshTime = 0f;
			if (DebugLogging.Value)
			{
				Log.LogInfo((object)("FacilityStartTeleport detected a new day/round. Waiting " + TeleportDelayAfterLanding.Value.ToString("0.0") + " seconds before teleporting."));
			}
		}
		if (teleportedThisDay)
		{
			return;
		}
		if (readyToTeleportTime < 0f)
		{
			readyToTeleportTime = Time.time + Mathf.Max(0f, TeleportDelayAfterLanding.Value);
		}
		else
		{
			if (Time.time < readyToTeleportTime)
			{
				return;
			}
			if (RequireDungeonFinished.Value && !DungeonFinishedGenerating())
			{
				if (DebugLogging.Value)
				{
					Log.LogInfo((object)"FacilityStartTeleport waiting for dungeon generation to finish before teleporting.");
				}
				readyToTeleportTime = Time.time + 1f;
			}
			else if (RefreshInsideNodesIfNeeded())
			{
				TeleportPlayersIntoFacility();
			}
		}
	}

	private bool IsOnPlayableMoon()
	{
		try
		{
			if ((Object)(object)StartOfRound.Instance == (Object)null || (Object)(object)RoundManager.Instance == (Object)null)
			{
				return false;
			}
			if (ReflectionUtil.GetBoolField(StartOfRound.Instance, "inShipPhase"))
			{
				return false;
			}
			if (ReflectionUtil.GetBoolField(StartOfRound.Instance, "travellingToNewLevel"))
			{
				return false;
			}
			if (!ReflectionUtil.GetBoolField(StartOfRound.Instance, "shipHasLanded") && Time.timeSinceLevelLoad < 10f)
			{
				return false;
			}
			if (SkipCompanyMoon != null && SkipCompanyMoon.Value && IsCompanyMoon())
			{
				return false;
			}
			return true;
		}
		catch
		{
			return false;
		}
	}

	private bool IsCompanyMoon()
	{
		try
		{
			object fieldObject = ReflectionUtil.GetFieldObject(StartOfRound.Instance, "currentLevel");
			if (fieldObject == null)
			{
				return false;
			}
			string text = ReflectionUtil.GetStringField(fieldObject, "PlanetName").ToLowerInvariant();
			string text2 = ReflectionUtil.GetStringField(fieldObject, "levelName").ToLowerInvariant();
			return text.Contains("gordion") || text.Contains("company") || text2.Contains("gordion") || text2.Contains("company");
		}
		catch
		{
			return false;
		}
	}

	private bool DungeonFinishedGenerating()
	{
		if ((Object)(object)RoundManager.Instance == (Object)null)
		{
			return false;
		}
		if (ReflectionUtil.GetBoolField(RoundManager.Instance, "dungeonFinishedGeneratingForAllPlayers"))
		{
			return true;
		}
		if (ReflectionUtil.GetBoolField(RoundManager.Instance, "playersFinishedGeneratingFloor"))
		{
			return true;
		}
		bool boolField = ReflectionUtil.GetBoolField(RoundManager.Instance, "dungeonIsGenerating");
		return ReflectionUtil.GetBoolField(RoundManager.Instance, "dungeonCompletedGenerating") && !boolField;
	}

	private int GetCurrentRoundKey()
	{
		int num = ReflectionUtil.GetIntField(StartOfRound.Instance, "randomMapSeed");
		if (num == 0 && (Object)(object)RoundManager.Instance != (Object)null)
		{
			num = ReflectionUtil.GetIntField(RoundManager.Instance, "randomMapSeed");
		}
		int intField = ReflectionUtil.GetIntField(StartOfRound.Instance, "currentLevelID");
		if (num == 0)
		{
			num = Mathf.RoundToInt(Time.timeSinceLevelLoad * 1000f);
		}
		return num ^ (intField << 16);
	}

	private bool RefreshInsideNodesIfNeeded()
	{
		if (cachedInsideNodes.Count > 0 && Time.time < nextNodeRefreshTime)
		{
			return true;
		}
		nextNodeRefreshTime = Time.time + 2f;
		cachedInsideNodes.Clear();
		AddInsideNodesFromRoundManager(cachedInsideNodes);
		if (cachedInsideNodes.Count == 0)
		{
			AddInsideNodesFromScene(cachedInsideNodes);
		}
		if (cachedInsideNodes.Count == 0)
		{
			AddEntranceFallbackNodes(cachedInsideNodes);
		}
		if (DebugLogging.Value)
		{
			Log.LogInfo((object)("FacilityStartTeleport inside spawn nodes found: " + cachedInsideNodes.Count));
		}
		return cachedInsideNodes.Count > 0;
	}

	private void AddInsideNodesFromRoundManager(List<Transform> list)
	{
		if (!((Object)(object)RoundManager.Instance == (Object)null))
		{
			object fieldObject = ReflectionUtil.GetFieldObject(RoundManager.Instance, "insideAINodes");
			AddTransformsFromObject(fieldObject, list);
			object fieldObject2 = ReflectionUtil.GetFieldObject(RoundManager.Instance, "allInsideAINodes");
			AddTransformsFromObject(fieldObject2, list);
		}
	}

	private void AddInsideNodesFromScene(List<Transform> list)
	{
		try
		{
			GameObject[] array = GameObject.FindGameObjectsWithTag("AINode");
			GameObject[] array2 = array;
			foreach (GameObject val in array2)
			{
				if (!((Object)(object)val == (Object)null))
				{
					string text = GetTransformPath(val.transform).ToLowerInvariant();
					if (!text.Contains("outside") && !text.Contains("ship") && !text.Contains("hangar") && (text.Contains("inside") || text.Contains("levelgeneration") || text.Contains("dungeon") || text.Contains("factory")))
					{
						AddUniqueTransform(val.transform, list);
					}
				}
			}
		}
		catch
		{
		}
	}

	private void AddEntranceFallbackNodes(List<Transform> list)
	{
		try
		{
			EntranceTeleport[] array = Object.FindObjectsOfType<EntranceTeleport>();
			EntranceTeleport[] array2 = array;
			foreach (EntranceTeleport val in array2)
			{
				if (!((Object)(object)val == (Object)null) && !ReflectionUtil.GetBoolField(val, "isEntranceToBuilding"))
				{
					AddUniqueTransform(((Component)val).transform, list);
				}
			}
		}
		catch
		{
		}
	}

	private void AddTransformsFromObject(object value, List<Transform> list)
	{
		if (value == null)
		{
			return;
		}
		Transform val = (Transform)((value is Transform) ? value : null);
		if ((Object)(object)val != (Object)null)
		{
			AddUniqueTransform(val, list);
			return;
		}
		GameObject val2 = (GameObject)((value is GameObject) ? value : null);
		if ((Object)(object)val2 != (Object)null)
		{
			AddUniqueTransform(val2.transform, list);
			return;
		}
		Component val3 = (Component)((value is Component) ? value : null);
		if ((Object)(object)val3 != (Object)null)
		{
			AddUniqueTransform(val3.transform, list);
		}
		else
		{
			if (!(value is IEnumerable enumerable))
			{
				return;
			}
			foreach (object item in enumerable)
			{
				if (item == null)
				{
					continue;
				}
				Transform val4 = (Transform)((item is Transform) ? item : null);
				if ((Object)(object)val4 != (Object)null)
				{
					AddUniqueTransform(val4, list);
					continue;
				}
				GameObject val5 = (GameObject)((item is GameObject) ? item : null);
				if ((Object)(object)val5 != (Object)null)
				{
					AddUniqueTransform(val5.transform, list);
					continue;
				}
				Component val6 = (Component)((item is Component) ? item : null);
				if ((Object)(object)val6 != (Object)null)
				{
					AddUniqueTransform(val6.transform, list);
				}
			}
		}
	}

	private void AddUniqueTransform(Transform transform, List<Transform> list)
	{
		if (!((Object)(object)transform == (Object)null) && !list.Contains(transform))
		{
			list.Add(transform);
		}
	}

	private void TeleportPlayersIntoFacility()
	{
		//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
		PlayerControllerB[] playersToMove = GetPlayersToMove();
		if (playersToMove == null || playersToMove.Length == 0)
		{
			return;
		}
		int num = 0;
		int num2 = 0;
		int currentRoundKey = GetCurrentRoundKey();
		for (int i = 0; i < playersToMove.Length; i++)
		{
			PlayerControllerB val = playersToMove[i];
			if (!ShouldMovePlayer(val))
			{
				continue;
			}
			int num3 = currentRoundKey ^ ((i + 1) * 92821) ^ GetPlayerClientIdSafe(val);
			if (!TryGetRandomFacilityPosition(num3, out var position, out var yRot))
			{
				if (DebugLogging.Value)
				{
					Log.LogWarning((object)("Could not find a safe facility spawn for player " + ((Object)val).name + "."));
				}
				continue;
			}
			SetPlayerInsideFactoryFields(val);
			TeleportPlayer(val, position, yRot);
			SetPlayerInsideFactoryFields(val);
			TriggerGameInsideFactoryStateOnce(val);
			if (MaybeGiveStartingFlashlight(val, num3 ^ 0x6A2B1C))
			{
				num2++;
			}
			num++;
			if (DebugLogging.Value)
			{
				Log.LogInfo((object)("Teleported player " + ((Object)val).name + " into facility at " + ((Vector3)(ref position)).ToString("F2")));
			}
		}
		if (num > 0)
		{
			teleportedThisDay = true;
			maintainInsideStateUntil = Time.time + Mathf.Clamp(MaintainInsideStateSeconds.Value, 0f, 3f);
			if (num2 > 0)
			{
				DoorTip("Facility Drop", "You wake up somewhere inside the facility with a flashlight.", warning: false);
			}
			else
			{
				DoorTip("Facility Drop", "You wake up somewhere inside the facility.", warning: false);
			}
		}
	}

	private PlayerControllerB[] GetPlayersToMove()
	{
		try
		{
			if (!TeleportAllActivePlayers.Value)
			{
				PlayerControllerB localPlayer = GetLocalPlayer();
				if ((Object)(object)localPlayer == (Object)null)
				{
					return (PlayerControllerB[])(object)new PlayerControllerB[0];
				}
				return (PlayerControllerB[])(object)new PlayerControllerB[1] { localPlayer };
			}
			object fieldObject = ReflectionUtil.GetFieldObject(StartOfRound.Instance, "allPlayerScripts");
			if (fieldObject is PlayerControllerB[] array && array.Length != 0)
			{
				return array;
			}
		}
		catch
		{
		}
		return Object.FindObjectsOfType<PlayerControllerB>();
	}

	private PlayerControllerB GetLocalPlayer()
	{
		try
		{
			if ((Object)(object)GameNetworkManager.Instance == (Object)null)
			{
				return null;
			}
			return GameNetworkManager.Instance.localPlayerController;
		}
		catch
		{
			return null;
		}
	}

	private bool ShouldMovePlayer(PlayerControllerB player)
	{
		if ((Object)(object)player == (Object)null)
		{
			return false;
		}
		if (!player.isPlayerControlled || player.isPlayerDead)
		{
			return false;
		}
		return true;
	}

	private bool TryGetRandomFacilityPosition(int seed, out Vector3 position, out float yRot)
	{
		//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_009a: Unknown result type (might be due to invalid IL or missing references)
		//IL_010e: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_0105: Unknown result type (might be due to invalid IL or missing references)
		//IL_010a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0176: Unknown result type (might be due to invalid IL or missing references)
		position = Vector3.zero;
		yRot = 0f;
		Random random = new Random(seed);
		if (cachedInsideNodes.Count == 0)
		{
			return false;
		}
		int num = Mathf.Max(10, MaxSpawnAttempts.Value);
		float num2 = Mathf.Max(0f, SpawnRadiusFromNode.Value);
		Vector3 val2 = default(Vector3);
		for (int i = 0; i < num; i++)
		{
			Transform val = cachedInsideNodes[random.Next(cachedInsideNodes.Count)];
			if (!((Object)(object)val == (Object)null))
			{
				if (!TryGetRoundManagerNavmeshPosition(val.position, seed ^ i, out var position2))
				{
					float num3 = (float)(random.NextDouble() * Math.PI * 2.0);
					float num4 = (float)random.NextDouble() * num2;
					((Vector3)(ref val2))..ctor(Mathf.Cos(num3) * num4, 0f, Mathf.Sin(num3) * num4);
					position2 = val.position + val2;
				}
				if (TryValidateAndAdjustSpawn(position2, out position))
				{
					yRot = (float)(random.NextDouble() * 360.0);
					return true;
				}
			}
		}
		for (int j = 0; j < cachedInsideNodes.Count; j++)
		{
			Transform val3 = cachedInsideNodes[j];
			if (!((Object)(object)val3 == (Object)null) && TryValidateAndAdjustSpawn(val3.position, out position))
			{
				yRot = (float)(random.NextDouble() * 360.0);
				return true;
			}
		}
		return false;
	}

	private bool TryGetInverseTeleporterPosition(int seed, out Vector3 position)
	{
		//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_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)
		position = Vector3.zero;
		try
		{
			ShipTeleporter[] array = Object.FindObjectsOfType<ShipTeleporter>();
			ShipTeleporter[] array2 = array;
			foreach (ShipTeleporter val in array2)
			{
				if (!((Object)(object)val == (Object)null) && val.isInverseTeleporter)
				{
					ReflectionUtil.SetIntField(val, "shipTeleporterSeed", seed);
					ReflectionUtil.CallNoArgMethod(val, "SetRandomSeed");
					object obj = ReflectionUtil.CallNoArgMethodReturn(val, "GetInverseTelePosition");
					if (obj is Vector3)
					{
						position = (Vector3)obj;
						return true;
					}
				}
			}
		}
		catch
		{
		}
		return false;
	}

	private bool TryGetRoundManagerNavmeshPosition(Vector3 center, int seed, out Vector3 position)
	{
		//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_0088: 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_00f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fd: 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_0111: Unknown result type (might be due to invalid IL or missing references)
		//IL_0113: Unknown result type (might be due to invalid IL or missing references)
		position = Vector3.zero;
		if ((Object)(object)RoundManager.Instance == (Object)null)
		{
			return false;
		}
		string[] array = new string[2] { "GetRandomNavMeshPositionInRadius", "GetRandomNavMeshPositionInRadiusSpherical" };
		for (int i = 0; i < array.Length; i++)
		{
			MethodInfo[] methods = ((object)RoundManager.Instance).GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			MethodInfo[] array2 = methods;
			foreach (MethodInfo methodInfo in array2)
			{
				if (methodInfo.Name != array[i] || !BuildNavmeshMethodArgs(methodInfo, center, seed, out var args))
				{
					continue;
				}
				try
				{
					object obj = methodInfo.Invoke(RoundManager.Instance, args);
					if (obj is Vector3)
					{
						position = (Vector3)obj;
						return true;
					}
					for (int k = 0; k < args.Length; k++)
					{
						if (args[k] is Vector3)
						{
							Vector3 val = (Vector3)args[k];
							if (val != Vector3.zero)
							{
								position = val;
								return true;
							}
						}
					}
				}
				catch
				{
				}
			}
		}
		return false;
	}

	private bool BuildNavmeshMethodArgs(MethodInfo method, Vector3 center, int seed, out object[] args)
	{
		//IL_0076: Unknown result type (might be due to invalid IL or missing references)
		args = null;
		try
		{
			ParameterInfo[] parameters = method.GetParameters();
			args = new object[parameters.Length];
			for (int i = 0; i < parameters.Length; i++)
			{
				Type parameterType = parameters[i].ParameterType;
				Type type = (parameterType.IsByRef ? parameterType.GetElementType() : parameterType);
				string text = ((parameters[i].Name == null) ? "" : parameters[i].Name.ToLowerInvariant());
				if (type == typeof(Vector3))
				{
					args[i] = center;
				}
				else if (type == typeof(float))
				{
					if (text.Contains("radius"))
					{
						args[i] = Mathf.Max(0.5f, NavmeshSearchRadius.Value);
					}
					else
					{
						args[i] = 0f;
					}
				}
				else if (type == typeof(int))
				{
					if (text.Contains("seed"))
					{
						args[i] = seed;
					}
					else
					{
						args[i] = -1;
					}
				}
				else if (type == typeof(bool))
				{
					args[i] = false;
				}
				else if (type == typeof(Random))
				{
					args[i] = new Random(seed);
				}
				else
				{
					args[i] = GetDefaultValue(type);
				}
			}
			return true;
		}
		catch
		{
			return false;
		}
	}

	private bool TryValidateAndAdjustSpawn(Vector3 candidate, out Vector3 adjustedPosition)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0003: Unknown result type (might be due to invalid IL or missing references)
		//IL_0009: 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_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_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_0061: Unknown result type (might be due to invalid IL or missing references)
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0080: Unknown result type (might be due to invalid IL or missing references)
		//IL_0085: 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_00aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e0: 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_0116: Unknown result type (might be due to invalid IL or missing references)
		adjustedPosition = candidate;
		if (TrySampleNavMeshReflective(candidate, Mathf.Max(0.5f, NavmeshSearchRadius.Value), out var position))
		{
			candidate = position;
		}
		if (!IsHeightNearInsideNode(candidate))
		{
			return false;
		}
		if (!TryFindFloor(candidate, out var floorPosition))
		{
			return false;
		}
		adjustedPosition = floorPosition + Vector3.up * Mathf.Max(0.1f, PlayerHeightOffset.Value);
		if (!LooksInsideFacility(adjustedPosition))
		{
			return false;
		}
		if (!IsHeightNearInsideNode(adjustedPosition))
		{
			return false;
		}
		if (!IsFarEnoughFromEntrances(adjustedPosition))
		{
			return false;
		}
		if (!CapsuleHasRoom(adjustedPosition))
		{
			return false;
		}
		if (!HasCeilingClearance(adjustedPosition))
		{
			return false;
		}
		if (!HasWallClearance(adjustedPosition))
		{
			return false;
		}
		return true;
	}

	private bool TryFindFloor(Vector3 candidate, out Vector3 floorPosition)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0003: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_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)
		floorPosition = candidate;
		float num = Mathf.Clamp(FloorRaycastHeight.Value, 0.25f, 2f);
		float num2 = Mathf.Clamp(FloorRaycastDistance.Value, 1f, 6f);
		Vector3 val = candidate + Vector3.up * num;
		float num3 = num2;
		RaycastHit[] array = Physics.RaycastAll(val, Vector3.down, num3, -1, (QueryTriggerInteraction)1);
		if (array == null || array.Length == 0)
		{
			return false;
		}
		Array.Sort(array, (RaycastHit a, RaycastHit b) => ((RaycastHit)(ref a)).distance.CompareTo(((RaycastHit)(ref b)).distance));
		for (int i = 0; i < array.Length; i++)
		{
			RaycastHit val2 = array[i];
			if (!((Object)(object)((RaycastHit)(ref val2)).collider == (Object)null) && !ShouldIgnoreColliderForSafety(((RaycastHit)(ref val2)).collider) && !(Vector3.Dot(((RaycastHit)(ref val2)).normal, Vector3.up) < 0.55f) && !ShouldRejectFloorCollider(((RaycastHit)(ref val2)).collider))
			{
				floorPosition = ((RaycastHit)(ref val2)).point;
				return true;
			}
		}
		return false;
	}

	private bool TrySampleNavMeshReflective(Vector3 center, float radius, out Vector3 position)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0003: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_013f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0144: Unknown result type (might be due to invalid IL or missing references)
		//IL_018c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0191: Unknown result type (might be due to invalid IL or missing references)
		position = center;
		try
		{
			Type type = Type.GetType("UnityEngine.AI.NavMesh, UnityEngine.AIModule");
			Type type2 = Type.GetType("UnityEngine.AI.NavMeshHit, UnityEngine.AIModule");
			if (type == null || type2 == null)
			{
				return false;
			}
			MethodInfo method = type.GetMethod("SamplePosition", BindingFlags.Static | BindingFlags.Public, null, new Type[4]
			{
				typeof(Vector3),
				type2.MakeByRefType(),
				typeof(float),
				typeof(int)
			}, null);
			if (method == null)
			{
				return false;
			}
			object obj = Activator.CreateInstance(type2);
			object[] array = new object[4] { center, obj, radius, -1 };
			object obj2 = method.Invoke(null, array);
			if (!(obj2 is bool) || !(bool)obj2)
			{
				return false;
			}
			object obj3 = array[1];
			PropertyInfo property = type2.GetProperty("position", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (property != null)
			{
				object value = property.GetValue(obj3, null);
				if (value is Vector3)
				{
					position = (Vector3)value;
					return true;
				}
			}
			FieldInfo field = type2.GetField("m_Position", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field != null)
			{
				object value2 = field.GetValue(obj3);
				if (value2 is Vector3)
				{
					position = (Vector3)value2;
					return true;
				}
			}
		}
		catch
		{
		}
		return false;
	}

	private bool IsHeightNearInsideNode(Vector3 position)
	{
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_0088: Unknown result type (might be due to invalid IL or missing references)
		//IL_008e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0099: 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_009d: 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_00be: Unknown result type (might be due to invalid IL or missing references)
		if (cachedInsideNodes.Count == 0)
		{
			return true;
		}
		float num = Mathf.Max(0.5f, MaximumHeightDifferenceFromNearestNode.Value);
		float num2 = float.MaxValue;
		float y = position.y;
		Vector2 val2 = default(Vector2);
		Vector2 val3 = default(Vector2);
		for (int i = 0; i < cachedInsideNodes.Count; i++)
		{
			Transform val = cachedInsideNodes[i];
			if (!((Object)(object)val == (Object)null))
			{
				((Vector2)(ref val2))..ctor(val.position.x, val.position.z);
				((Vector2)(ref val3))..ctor(position.x, position.z);
				Vector2 val4 = val2 - val3;
				float sqrMagnitude = ((Vector2)(ref val4)).sqrMagnitude;
				if (sqrMagnitude < num2)
				{
					num2 = sqrMagnitude;
					y = val.position.y;
				}
			}
		}
		return Mathf.Abs(position.y - y) <= num;
	}

	private bool ShouldRejectFloorCollider(Collider collider)
	{
		if ((Object)(object)collider == (Object)null)
		{
			return true;
		}
		if (RejectPipeAndPropFloors != null && !RejectPipeAndPropFloors.Value)
		{
			return false;
		}
		string text = GetTransformPath(((Component)collider).transform).ToLowerInvariant();
		string text2 = ((Object)((Component)collider).gameObject).name.ToLowerInvariant();
		if (text.Contains("pipe") || text.Contains("socket") || text.Contains("steam") || text.Contains("valve") || text.Contains("vent") || text.Contains("rail") || text.Contains("ceiling") || text.Contains("roof") || text.Contains("wire") || text.Contains("cable") || text.Contains("prop") || text.Contains("lung") || text2.Contains("pipe") || text2.Contains("socket") || text2.Contains("steam") || text2.Contains("valve") || text2.Contains("vent") || text2.Contains("rail") || text2.Contains("ceiling") || text2.Contains("roof") || text2.Contains("wire") || text2.Contains("cable"))
		{
			return true;
		}
		return false;
	}

	private bool CapsuleHasRoom(Vector3 position)
	{
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: 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)
		float num = Mathf.Clamp(CapsuleRadius.Value, 0.1f, 1f);
		float num2 = Mathf.Clamp(CapsuleHeight.Value, 1f, 3f);
		Vector3 val = position + Vector3.up * 0.35f;
		Vector3 val2 = position + Vector3.up * num2;
		Collider[] array = Physics.OverlapCapsule(val, val2, num, -1, (QueryTriggerInteraction)1);
		if (array == null || array.Length == 0)
		{
			return true;
		}
		foreach (Collider val3 in array)
		{
			if (!((Object)(object)val3 == (Object)null) && !ShouldIgnoreColliderForSafety(val3))
			{
				return false;
			}
		}
		return true;
	}

	private bool HasCeilingClearance(Vector3 position)
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: 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_0099: Unknown result type (might be due to invalid IL or missing references)
		//IL_009e: Unknown result type (might be due to invalid IL or missing references)
		float num = Mathf.Max(1.25f, MinimumCeilingClearance.Value);
		Vector3 val = position + Vector3.up * 0.35f;
		RaycastHit[] array = Physics.SphereCastAll(val, Mathf.Max(0.1f, CapsuleRadius.Value * 0.75f), Vector3.up, num, -1, (QueryTriggerInteraction)1);
		if (array == null || array.Length == 0)
		{
			return true;
		}
		Array.Sort(array, (RaycastHit a, RaycastHit b) => ((RaycastHit)(ref a)).distance.CompareTo(((RaycastHit)(ref b)).distance));
		for (int i = 0; i < array.Length; i++)
		{
			RaycastHit val2 = array[i];
			if (!((Object)(object)((RaycastHit)(ref val2)).collider == (Object)null) && !ShouldIgnoreColliderForSafety(((RaycastHit)(ref val2)).collider))
			{
				return false;
			}
		}
		return true;
	}

	private bool HasWallClearance(Vector3 position)
	{
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_005d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_0081: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_008b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0090: Unknown result type (might be due to invalid IL or missing references)
		//IL_0094: Unknown result type (might be due to invalid IL or missing references)
		//IL_0099: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_00af: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00de: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e8: 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_00f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0105: 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)
		float num = Mathf.Clamp(MinimumWallClearance.Value, 0f, 2f);
		if (num <= 0.01f)
		{
			return true;
		}
		Vector3 val = position + Vector3.up * 1.05f;
		Vector3[] obj = new Vector3[8]
		{
			Vector3.forward,
			Vector3.back,
			Vector3.left,
			Vector3.right,
			default(Vector3),
			default(Vector3),
			default(Vector3),
			default(Vector3)
		};
		Vector3 val2 = Vector3.forward + Vector3.left;
		obj[4] = ((Vector3)(ref val2)).normalized;
		val2 = Vector3.forward + Vector3.right;
		obj[5] = ((Vector3)(ref val2)).normalized;
		val2 = Vector3.back + Vector3.left;
		obj[6] = ((Vector3)(ref val2)).normalized;
		val2 = Vector3.back + Vector3.right;
		obj[7] = ((Vector3)(ref val2)).normalized;
		Vector3[] array = (Vector3[])(object)obj;
		for (int i = 0; i < array.Length; i++)
		{
			RaycastHit[] array2 = Physics.RaycastAll(val, array[i], num, -1, (QueryTriggerInteraction)1);
			if (array2 == null || array2.Length == 0)
			{
				continue;
			}
			Array.Sort(array2, (RaycastHit a, RaycastHit b) => ((RaycastHit)(ref a)).distance.CompareTo(((RaycastHit)(ref b)).distance));
			for (int j = 0; j < array2.Length; j++)
			{
				if (!((Object)(object)((RaycastHit)(ref array2[j])).collider == (Object)null) && !ShouldIgnoreColliderForSafety(((RaycastHit)(ref array2[j])).collider))
				{
					return false;
				}
			}
		}
		return true;
	}

	private bool IsFarEnoughFromEntrances(Vector3 position)
	{
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0081: 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_00a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
		float num = ((MinimumDistanceFromEntrance == null) ? 8f : Mathf.Max(0f, MinimumDistanceFromEntrance.Value));
		if (num <= 0.01f)
		{
			return true;
		}
		try
		{
			EntranceTeleport[] array = Object.FindObjectsOfType<EntranceTeleport>();
			Vector3 val2 = default(Vector3);
			Vector3 val3 = default(Vector3);
			foreach (EntranceTeleport val in array)
			{
				if (!((Object)(object)val == (Object)null))
				{
					((Vector3)(ref val2))..ctor(position.x, 0f, position.z);
					((Vector3)(ref val3))..ctor(((Component)val).transform.position.x, 0f, ((Component)val).transform.position.z);
					if (Vector3.Distance(val2, val3) < num)
					{
						return false;
					}
				}
			}
		}
		catch
		{
		}
		return true;
	}

	private bool LooksInsideFacility(Vector3 position)
	{
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		string text = "";
		float num = float.MaxValue;
		for (int i = 0; i < cachedInsideNodes.Count; i++)
		{
			Transform val = cachedInsideNodes[i];
			if (!((Object)(object)val == (Object)null))
			{
				float num2 = Vector3.SqrMagnitude(val.position - position);
				if (num2 < num)
				{
					num = num2;
					text = GetTransformPath(val).ToLowerInvariant();
				}
			}
		}
		if (text.Contains("outside") || text.Contains("hangar") || text.Contains("ship"))
		{
			return false;
		}
		return true;
	}

	private bool ShouldIgnoreColliderForSafety(Collider collider)
	{
		if ((Object)(object)collider == (Object)null)
		{
			return true;
		}
		if (collider.isTrigger)
		{
			return true;
		}
		string text = GetTransformPath(((Component)collider).transform).ToLowerInvariant();
		string text2 = ((Object)((Component)collider).gameObject).name.ToLowerInvariant();
		if (text.Contains("player") || text.Contains("enemy") || text.Contains("trigger") || text.Contains("scan") || text.Contains("item") || text.Contains("grabbable") || text.Contains("ainode") || text.Contains("audio") || text.Contains("interact") || text2.Contains("player") || text2.Contains("trigger") || text2.Contains("scan") || text2.Contains("ainode") || text2.Contains("interact"))
		{
			return true;
		}
		return false;
	}

	private void TeleportPlayer(PlayerControllerB player, Vector3 position, float yRot)
	{
		//IL_0014: 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_0071: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)player == (Object)null) && !CallTeleportPlayerMethod(player, position, yRot))
		{
			CharacterController component = ((Component)player).GetComponent<CharacterController>();
			bool enabled = (Object)(object)component != (Object)null && ((Collider)component).enabled;
			if ((Object)(object)component != (Object)null)
			{
				((Collider)component).enabled = false;
			}
			((Component)player).transform.position = position;
			((Component)player).transform.rotation = Quaternion.Euler(0f, yRot, 0f);
			if ((Object)(object)component != (Object)null)
			{
				((Collider)component).enabled = enabled;
			}
		}
	}

	private bool CallTeleportPlayerMethod(PlayerControllerB player, Vector3 position, float yRot)
	{
		//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			MethodInfo[] methods = typeof(PlayerControllerB).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			MethodInfo[] array = methods;
			foreach (MethodInfo methodInfo in array)
			{
				if (methodInfo.Name != "TeleportPlayer")
				{
					continue;
				}
				ParameterInfo[] parameters = methodInfo.GetParameters();
				bool flag = false;
				for (int j = 0; j < parameters.Length; j++)
				{
					if (parameters[j].ParameterType == typeof(Vector3))
					{
						flag = true;
						break;
					}
				}
				if (!flag)
				{
					continue;
				}
				object[] array2 = new object[parameters.Length];
				for (int k = 0; k < parameters.Length; k++)
				{
					Type parameterType = parameters[k].ParameterType;
					string text = ((parameters[k].Name == null) ? "" : parameters[k].Name.ToLowerInvariant());
					if (parameterType == typeof(Vector3))
					{
						array2[k] = position;
					}
					else if (parameterType == typeof(float))
					{
						array2[k] = yRot;
					}
					else if (parameterType == typeof(bool))
					{
						if (text.Contains("rotation") || text.Contains("rot"))
						{
							array2[k] = true;
						}
						else if (text.Contains("enable"))
						{
							array2[k] = true;
						}
						else
						{
							array2[k] = false;
						}
					}
					else
					{
						array2[k] = GetDefaultValue(parameterType);
					}
				}
				methodInfo.Invoke(player, array2);
				return true;
			}
		}
		catch (Exception ex)
		{
			if (DebugLogging != null && DebugLogging.Value && Log != null)
			{
				Log.LogWarning((object)("TeleportPlayer reflection failed, using transform fallback: " + ex.Message));
			}
		}
		return false;
	}

	private bool MaybeGiveStartingFlashlight(PlayerControllerB player, int seed)
	{
		if ((Object)(object)player == (Object)null)
		{
			return false;
		}
		if (!IsHostOrServer())
		{
			return false;
		}
		if (GiveFlashlightIfInventoryEmpty == null || !GiveFlashlightIfInventoryEmpty.Value)
		{
			return false;
		}
		if (PlayerHasAnyInventoryItem(player))
		{
			return false;
		}
		Random random = new Random(seed);
		if (random.NextDouble() > (double)Mathf.Clamp01(FlashlightGiveChance.Value))
		{
			return false;
		}
		bool flag = random.NextDouble() <= (double)Mathf.Clamp01(ProFlashlightChance.Value);
		Item val = null;
		if (flag)
		{
			val = FindItemByConfigNames(ProFlashlightNames.Value);
		}
		if ((Object)(object)val == (Object)null)
		{
			val = FindItemByConfigNames(NormalFlashlightNames.Value);
		}
		if ((Object)(object)val == (Object)null && !flag)
		{
			val = FindItemByConfigNames(ProFlashlightNames.Value);
		}
		if ((Object)(object)val == (Object)null)
		{
			if (DebugLogging.Value)
			{
				Log.LogWarning((object)"Could not find normal or pro flashlight Item in allItemsList.");
			}
			return false;
		}
		bool flag2 = GiveItemToPlayer(player, val);
		if (flag2 && DebugLogging.Value)
		{
			Log.LogInfo((object)("Gave starting item to " + ((Object)player).name + ": " + val.itemName));
		}
		return flag2;
	}

	private bool PlayerHasAnyInventoryItem(PlayerControllerB player)
	{
		try
		{
			GrabbableObject[] itemSlots = player.ItemSlots;
			if (itemSlots != null)
			{
				for (int i = 0; i < itemSlots.Length; i++)
				{
					if ((Object)(object)itemSlots[i] != (Object)null)
					{
						return true;
					}
				}
			}
			object fieldObject = ReflectionUtil.GetFieldObject(player, "currentlyHeldObjectServer");
			object fieldObject2 = ReflectionUtil.GetFieldObject(player, "currentlyHeldObject");
			if (fieldObject != null || fieldObject2 != null)
			{
				return true;
			}
		}
		catch
		{
		}
		return false;
	}

	private Item FindItemByConfigNames(string namesCsv)
	{
		List<Item> allGameItems = GetAllGameItems();
		if (allGameItems.Count == 0)
		{
			return null;
		}
		string[] array = SplitCsv(namesCsv);
		for (int i = 0; i < array.Length; i++)
		{
			string text = NormalizeName(array[i]);
			if (string.IsNullOrEmpty(text))
			{
				continue;
			}
			for (int j = 0; j < allGameItems.Count; j++)
			{
				Item val = allGameItems[j];
				if (!((Object)(object)val == (Object)null) && NormalizeName(val.itemName) == text)
				{
					return val;
				}
			}
		}
		for (int k = 0; k < array.Length; k++)
		{
			string text2 = NormalizeName(array[k]);
			if (string.IsNullOrEmpty(text2))
			{
				continue;
			}
			for (int l = 0; l < allGameItems.Count; l++)
			{
				Item val2 = allGameItems[l];
				if (!((Object)(object)val2 == (Object)null))
				{
					string text3 = NormalizeName(val2.itemName);
					if (text3.Contains(text2) || text2.Contains(text3))
					{
						return val2;
					}
				}
			}
		}
		return null;
	}

	private List<Item> GetAllGameItems()
	{
		List<Item> list = new List<Item>();
		try
		{
			object fieldObject = ReflectionUtil.GetFieldObject(StartOfRound.Instance, "allItemsList");
			object fieldObject2 = ReflectionUtil.GetFieldObject(fieldObject, "itemsList");
			if (fieldObject2 is IEnumerable enumerable)
			{
				foreach (object item in enumerable)
				{
					Item val = (Item)((item is Item) ? item : null);
					if ((Object)(object)val != (Object)null && !list.Contains(val))
					{
						list.Add(val);
					}
				}
			}
		}
		catch
		{
		}
		return list;
	}

	private string[] SplitCsv(string value)
	{
		if (string.IsNullOrEmpty(value))
		{
			return new string[0];
		}
		return value.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
	}

	private string NormalizeName(string value)
	{
		if (string.IsNullOrEmpty(value))
		{
			return "";
		}
		return value.ToLowerInvariant().Replace(" ", "").Replace("-", "")
			.Replace("_", "")
			.Trim();
	}

	private bool GiveItemToPlayer(PlayerControllerB player, Item itemDef)
	{
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if (!IsHostOrServer())
			{
				return false;
			}
			if ((Object)(object)player == (Object)null || (Object)(object)itemDef == (Object)null || (Object)(object)itemDef.spawnPrefab == (Object)null)
			{
				return false;
			}
			if (GetFirstEmptyItemSlot(player) < 0)
			{
				return false;
			}
			Vector3 val = FindStartingItemDropPosition(player);
			GameObject val2 = Object.Instantiate<GameObject>(itemDef.spawnPrefab, val, Quaternion.identity);
			if ((Object)(object)val2 == (Object)null)
			{
				return false;
			}
			GrabbableObject component = val2.GetComponent<GrabbableObject>();
			if ((Object)(object)component == (Object)null)
			{
				Object.Destroy((Object)(object)val2);
				return false;
			}
			SetupStartingItemAsRealDroppedItem(val2, component, itemDef, player);
			TryFillBattery(component);
			TrySpawnNetworkObject(val2);
			if (EquipGivenFlashlight != null && EquipGivenFlashlight.Value)
			{
				((MonoBehaviour)this).StartCoroutine(TryVanillaPickupAfterSpawn(player, component));
			}
			return true;
		}
		catch (Exception ex)
		{
			if (DebugLogging.Value)
			{
				Log.LogWarning((object)("Failed to spawn starting flashlight: " + ex.Message));
			}
		}
		return false;
	}

	private Vector3 FindStartingItemDropPosition(PlayerControllerB player)
	{
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_009f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_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_009c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)player == (Object)null)
		{
			return Vector3.zero;
		}
		Vector3 val = ((Component)player).transform.position + ((Component)player).transform.forward * 0.65f + Vector3.up * 0.75f;
		RaycastHit val2 = default(RaycastHit);
		if (Physics.Raycast(val + Vector3.up * 1f, Vector3.down, ref val2, 4f, -1, (QueryTriggerInteraction)1))
		{
			return ((RaycastHit)(ref val2)).point + Vector3.up * 0.25f;
		}
		return val;
	}

	private void SetupStartingItemAsRealDroppedItem(GameObject itemObject, GrabbableObject grabbable, Item itemDef, PlayerControllerB player)
	{
		if (!((Object)(object)itemObject == (Object)null) && !((Object)(object)grabbable == (Object)null))
		{
			itemObject.transform.SetParent((Transform)null, true);
			grabbable.itemProperties = itemDef;
			grabbable.grabbable = true;
			grabbable.grabbableToEnemies = true;
			grabbable.hasHitGround = true;
			grabbable.fallTime = 0f;
			grabbable.playerHeldBy = null;
			grabbable.isHeld = false;
			grabbable.isPocketed = false;
			grabbable.isInElevator = false;
			grabbable.isInShipRoom = false;
			ReflectionUtil.SetBoolField(grabbable, "heldByPlayerOnServer", value: false);
			ReflectionUtil.SetBoolField(grabbable, "isInFactory", value: true);
			ReflectionUtil.SetBoolField(grabbable, "isInShipRoom", value: false);
			ReflectionUtil.SetBoolField(grabbable, "isInElevator", value: false);
			ReflectionUtil.SetBoolField(grabbable, "wasOwnerLastFrame", value: false);
			ReflectionUtil.SetBoolField(grabbable, "deactivated", value: false);
			ReflectionUtil.SetFieldObject(grabbable, "playerHeldBy", null);
			ReflectionUtil.SetFieldObject(grabbable, "parentObject", null);
			ReflectionUtil.CallFlexibleMethod(grabbable, "EnableItemMeshes", new object[1] { true });
			ReflectionUtil.CallFlexibleMethod(grabbable, "EnablePhysics", new object[1] { true });
			ReflectionUtil.CallNoArgMethod(grabbable, "FallToGround");
		}
	}

	[IteratorStateMachine(typeof(<TryVanillaPickupAfterSpawn>d__84))]
	private IEnumerator TryVanillaPickupAfterSpawn(PlayerControllerB player, GrabbableObject grabbable)
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <TryVanillaPickupAfterSpawn>d__84(0)
		{
			<>4__this = this,
			player = player,
			grabbable = grabbable
		};
	}

	private bool IsItemInPlayerInventory(PlayerControllerB player, GrabbableObject item)
	{
		try
		{
			if ((Object)(object)player == (Object)null || (Object)(object)item == (Object)null || player.ItemSlots == null)
			{
				return false;
			}
			for (int i = 0; i < player.ItemSlots.Length; i++)
			{
				if ((Object)(object)player.ItemSlots[i] == (Object)(object)item)
				{
					return true;
				}
			}
		}
		catch
		{
		}
		return false;
	}

	private bool TryCallGrabObjectServerRpc(PlayerControllerB player, GameObject itemObject)
	{
		try
		{
			if ((Object)(object)player == (Object)null || (Object)(object)itemObject == (Object)null)
			{
				return false;
			}
			Component networkObjectComponent = GetNetworkObjectComponent(itemObject);
			if ((Object)(object)networkObjectComponent == (Object)null)
			{
				return false;
			}
			MethodInfo[] methods = ((object)player).GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			MethodInfo[] array = methods;
			foreach (MethodInfo methodInfo in array)
			{
				if (methodInfo.Name != "GrabObjectServerRpc")
				{
					continue;
				}
				ParameterInfo[] parameters = methodInfo.GetParameters();
				object[] array2 = new object[parameters.Length];
				bool flag = true;
				for (int j = 0; j < parameters.Length; j++)
				{
					Type parameterType = parameters[j].ParameterType;
					Type type = (parameterType.IsByRef ? parameterType.GetElementType() : parameterType);
					if (type.Name == "NetworkObjectReference")
					{
						object obj = CreateNetworkObjectReference(type, networkObjectComponent);
						if (obj == null)
						{
							flag = false;
							break;
						}
						array2[j] = obj;
					}
					else if (type == typeof(bool))
					{
						array2[j] = false;
					}
					else if (type == typeof(int))
					{
						array2[j] = 0;
					}
					else
					{
						array2[j] = GetDefaultValue(type);
					}
				}
				if (flag)
				{
					methodInfo.Invoke(player, array2);
					return true;
				}
			}
		}
		catch
		{
		}
		return false;
	}

	private Component GetNetworkObjectComponent(GameObject itemObject)
	{
		if ((Object)(object)itemObject == (Object)null)
		{
			return null;
		}
		Component[] components = itemObject.GetComponents<Component>();
		foreach (Component val in components)
		{
			if ((Object)(object)val != (Object)null && ((object)val).GetType().Name == "NetworkObject")
			{
				return val;
			}
		}
		return null;
	}

	private object CreateNetworkObjectReference(Type referenceType, Component networkObject)
	{
		try
		{
			if (referenceType == null || (Object)(object)networkObject == (Object)null)
			{
				return null;
			}
			ConstructorInfo[] constructors = referenceType.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			ConstructorInfo[] array = constructors;
			foreach (ConstructorInfo constructorInfo in array)
			{
				ParameterInfo[] parameters = constructorInfo.GetParameters();
				if (parameters.Length == 1)
				{
					Type parameterType = parameters[0].ParameterType;
					if (parameterType.IsAssignableFrom(((object)networkObject).GetType()))
					{
						return constructorInfo.Invoke(new object[1] { networkObject });
					}
				}
			}
		}
		catch
		{
		}
		return null;
	}

	private int GetFirstEmptyItemSlot(PlayerControllerB player)
	{
		try
		{
			if ((Object)(object)player == (Object)null)
			{
				return -1;
			}
			GrabbableObject[] itemSlots = player.ItemSlots;
			if (itemSlots != null)
			{
				for (int i = 0; i < itemSlots.Length; i++)
				{
					if ((Object)(object)itemSlots[i] == (Object)null)
					{
						return i;
					}
				}
			}
		}
		catch
		{
		}
		return -1;
	}

	private void ForceItemIntoPlayerSlot(PlayerControllerB player, GrabbableObject grabbable, int slot)
	{
		//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00de: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)player == (Object)null) && !((Object)(object)grabbable == (Object)null))
		{
			GrabbableObject[] itemSlots = player.ItemSlots;
			if (itemSlots != null && slot >= 0 && slot < itemSlots.Length)
			{
				itemSlots[slot] = grabbable;
			}
			Transform val = ReflectionUtil.GetTransformField(player, "localItemHolder");
			if ((Object)(object)val == (Object)null)
			{
				val = ReflectionUtil.GetTransformField(player, "serverItemHolder");
			}
			if ((Object)(object)val == (Object)null)
			{
				val = ((Component)player).transform;
			}
			grabbable.parentObject = val;
			((Component)grabbable).transform.SetParent(val, false);
			((Component)grabbable).transform.localPosition = (((Object)(object)grabbable.itemProperties != (Object)null) ? grabbable.itemProperties.positionOffset : Vector3.zero);
			((Component)grabbable).transform.localEulerAngles = (((Object)(object)grabbable.itemProperties != (Object)null) ? grabbable.itemProperties.rotationOffset : Vector3.zero);
			ReflectionUtil.SetIntField(player, "currentItemSlot", slot);
			ReflectionUtil.SetBoolField(player, "isHoldingObject", value: true);
			ReflectionUtil.SetBoolField(player, "twoHanded", (Object)(object)grabbable.itemProperties != (Object)null && grabbable.itemProperties.twoHanded);
			ReflectionUtil.SetFieldObject(player, "currentlyHeldObjectServer", grabbable);
			ReflectionUtil.SetFieldObject(player, "currentlyHeldObject", grabbable);
			ReflectionUtil.CallNoArgMethod(grabbable, "GrabItemOnClient");
			ReflectionUtil.CallNoArgMethod(grabbable, "GrabItem");
			if (EquipGivenFlashlight == null || EquipGivenFlashlight.Value)
			{
				ReflectionUtil.CallFlexibleMethod(player, "SwitchToItemSlot", new object[2] { slot, grabbable });
				ReflectionUtil.CallNoArgMethod(grabbable, "EquipItem");
			}
			else
			{
				ReflectionUtil.CallNoArgMethod(grabbable, "PocketItem");
			}
			ReflectionUtil.CallFlexibleMethod(grabbable, "EnableItemMeshes", new object[1] { true });
		}
	}

	private void TrySpawnNetworkObject(GameObject itemObject)
	{
		if ((Object)(object)itemObject == (Object)null)
		{
			return;
		}
		if (!IsHostOrServer())
		{
			if (DebugLogging != null && DebugLogging.Value && Log != null)
			{
				Log.LogWarning((object)"Blocked a non-host client from spawning a starting flashlight NetworkObject.");
			}
			Object.Destroy((Object)(object)itemObject);
			return;
		}
		try
		{
			Component[] components = itemObject.GetComponents<Component>();
			foreach (Component val in components)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				Type type = ((object)val).GetType();
				if (type.Name != "NetworkObject")
				{
					continue;
				}
				MethodInfo method = type.GetMethod("Spawn", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
				if (method != null)
				{
					method.Invoke(val, null);
					break;
				}
				MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				MethodInfo[] array = methods;
				foreach (MethodInfo methodInfo in array)
				{
					if (methodInfo.Name != "Spawn")
					{
						continue;
					}
					ParameterInfo[] parameters = methodInfo.GetParameters();
					object[] array2 = new object[parameters.Length];
					for (int k = 0; k < parameters.Length; k++)
					{
						if (parameters[k].ParameterType == typeof(bool))
						{
							array2[k] = true;
						}
						else
						{
							array2[k] = GetDefaultValue(parameters[k].ParameterType);
						}
					}
					methodInfo.Invoke(val, array2);
					return;
				}
			}
		}
		catch
		{
		}
	}

	private void TryFillBattery(GrabbableObject grabbable)
	{
		try
		{
			if ((Object)(object)grabbable == (Object)null)
			{
				return;
			}
			FieldInfo field = typeof(GrabbableObject).GetField("insertedBattery", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (!(field == null))
			{
				object boxedStruct = field.GetValue(grabbable);
				if (boxedStruct == null)
				{
					boxedStruct = Activator.CreateInstance(field.FieldType);
				}
				ReflectionUtil.SetFieldOnBoxedStruct(ref boxedStruct, "empty", false);
				ReflectionUtil.SetFieldOnBoxedStruct(ref boxedStruct, "charge", 1f);
				field.SetValue(grabbable, boxedStruct);
			}
		}
		catch
		{
		}
	}

	private bool IsHostOrServer()
	{
		try
		{
			PlayerControllerB localPlayer = GetLocalPlayer();
			if ((Object)(object)localPlayer != (Object)null && localPlayer.isHostPlayerObject)
			{
				return true;
			}
			Type type = FindTypeByName("Unity.Netcode.NetworkManager");
			if (type != null)
			{
				object obj = null;
				PropertyInfo property = type.GetProperty("Singleton", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				if (property != null)
				{
					obj = property.GetValue(null, null);
				}
				if (obj == null)
				{
					FieldInfo field = type.GetField("Singleton", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
					if (field != null)
					{
						obj = field.GetValue(null);
					}
				}
				if (obj != null && (GetBoolPropertyOrField(obj, "IsServer") || GetBoolPropertyOrField(obj, "IsHost")))
				{
					return true;
				}
			}
			if ((Object)(object)StartOfRound.Instance != (Object)null)
			{
				object instance = StartOfRound.Instance;
				if (GetBoolPropertyOrField(instance, "IsServer") || GetBoolPropertyOrField(instance, "IsHost"))
				{
					return true;
				}
			}
		}
		catch
		{
		}
		return false;
	}

	private Type FindTypeByName(string fullName)
	{
		try
		{
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			for (int i = 0; i < assemblies.Length; i++)
			{
				Type type = assemblies[i].GetType(fullName, throwOnError: false);
				if (type != null)
				{
					return type;
				}
			}
		}
		catch
		{
		}
		return null;
	}

	private bool GetBoolPropertyOrField(object instance, string name)
	{
		if (instance == null || string.IsNullOrEmpty(name))
		{
			return false;
		}
		try
		{
			Type type = instance.GetType();
			PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (property != null && property.PropertyType == typeof(bool))
			{
				return (bool)property.GetValue(instance, null);
			}
			FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field != null && field.FieldType == typeof(bool))
			{
				return (bool)field.GetValue(instance);
			}
		}
		catch
		{
		}
		return false;
	}

	private object GetDefaultValue(Type type)
	{
		if (type == null)
		{
			return null;
		}
		if (type.IsByRef)
		{
			type = type.GetElementType();
		}
		if (type.IsValueType)
		{
			return Activator.CreateInstance(type);
		}
		return null;
	}

	private void SetPlayerInsideFactoryFields(PlayerControllerB player)
	{
		if (!((Object)(object)player == (Object)null))
		{
			ReflectionUtil.SetBoolField(player, "isInsideFactory", value: true);
			ReflectionUtil.SetBoolField(player, "isInFactory", value: true);
			ReflectionUtil.SetBoolField(player, "isInHangarShipRoom", value: false);
			ReflectionUtil.SetBoolField(player, "isInElevator", value: false);
			ReflectionUtil.SetBoolField(player, "isPlayerAlone", value: false);
		}
	}

	private void TriggerGameInsideFactoryStateOnce(PlayerControllerB player)
	{
		if (!((Object)(object)player == (Object)null))
		{
			ulong playerClientIdSafeUlong = GetPlayerClientIdSafeUlong(player);
			int num = (int)Mathf.Clamp((float)playerClientIdSafeUlong, 0f, 9999f);
			ReflectionUtil.CallFlexibleMethod(StartOfRound.Instance, "SwitchIsInsideFactoryRpc", new object[3] { playerClientIdSafeUlong, num, true });
			ApplyLocalInsideVisualState(player);
		}
	}

	private void ApplyLocalInsideVisualState(PlayerControllerB player)
	{
		if ((Object)(object)player == (Object)null)
		{
			return;
		}
		PlayerControllerB localPlayer = GetLocalPlayer();
		if (!((Object)(object)localPlayer != (Object)null) || !((Object)(object)player != (Object)(object)localPlayer))
		{
			SetPlayerInsideFactoryFields(player);
			if (ApplyDynamicInsideAudioState == null || ApplyDynamicInsideAudioState.Value)
			{
				ApplyDynamicInsideAudioAndLighting(player);
			}
			ReflectionUtil.CallNoArgMethod(player, "UpdateCameraOutsideOrInside");
			RefreshInsideTimeAndLighting();
			if (HideClockDuringInsideSpawn == null || HideClockDuringInsideSpawn.Value)
			{
				TrySetClockVisible(visible: false);
			}
		}
	}

	private void ApplyDynamicInsideAudioAndLighting(PlayerControllerB player)
	{
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)player == (Object)null)
		{
			return;
		}
		AudioReverbTrigger val = FindBestInsideAudioTrigger(((Component)player).transform.position);
		if ((Object)(object)val == (Object)null)
		{
			if (DebugLogging != null && DebugLogging.Value && Log != null)
			{
				Log.LogWarning((object)"FacilityStartTeleport could not find an inside AudioReverbTrigger. Falling back to player flags only.");
			}
			return;
		}
		bool flag = false;
		try
		{
			flag = ReflectionUtil.CallFlexibleMethod(val, "ChangeAudioReverbForPlayer", new object[1] { player });
		}
		catch
		{
			flag = false;
		}
		ReflectionUtil.SetFieldObject(player, "currentAudioTrigger", val);
		ReflectionUtil.SetFieldObject(player, "currentAudioTriggerB", null);
		object fieldObject = ReflectionUtil.GetFieldObject(val, "reverbPreset");
		if (fieldObject != null)
		{
			ReflectionUtil.SetFieldObject(player, "reverbPreset", fieldObject);
		}
		SetPlayerInsideFactoryFields(player);
		RefreshInsideTimeAndLighting();
		if (DebugLogging != null && DebugLogging.Value && Log != null)
		{
			string text = ((fieldObject == null) ? "null" : fieldObject.ToString());
			Log.LogInfo((object)("Applied dynamic inside audio trigger: " + GetTransformPath(((Component)val).transform) + " preset=" + text + " calledChangeAudio=" + flag));
		}
	}

	private AudioReverbTrigger FindBestInsideAudioTrigger(Vector3 playerPosition)
	{
		//IL_007c: Unknown result type (might be due to invalid IL or missing references)
		AudioReverbTrigger[] array = null;
		try
		{
			array = Object.FindObjectsOfType<AudioReverbTrigger>();
		}
		catch
		{
			return null;
		}
		if (array == null || array.Length == 0)
		{
			return null;
		}
		AudioReverbTrigger result = null;
		float num = float.MinValue;
		float tieRadius = ((InsideAudioSearchRadius == null) ? 60f : Mathf.Max(1f, InsideAudioSearchRadius.Value));
		foreach (AudioReverbTrigger val in array)
		{
			if (!((Object)(object)val == (Object)null))
			{
				float num2 = ScoreInsideAudioTrigger(val, playerPosition, tieRadius);
				if (num2 > num)
				{
					num = num2;
					result = val;
				}
			}
		}
		if (num < 10f)
		{
			return null;
		}
		return result;
	}

	private float ScoreInsideAudioTrigger(AudioReverbTrigger trigger, Vector3 playerPosition, float tieRadius)
	{
		//IL_030c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0311: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)trigger == (Object)null)
		{
			return float.MinValue;
		}
		string text = GetTransformPath(((Component)trigger).transform).ToLowerInvariant();
		string text2 = (((Object)(object)((Component)trigger).gameObject == (Object)null) ? "" : ((Object)((Component)trigger).gameObject).name.ToLowerInvariant());
		float num = 0f;
		bool boolField = ReflectionUtil.GetBoolField(trigger, "isShipRoom");
		bool boolField2 = ReflectionUtil.GetBoolField(trigger, "setInsideAtmosphere");
		bool boolField3 = ReflectionUtil.GetBoolField(trigger, "insideLighting");
		bool boolField4 = ReflectionUtil.GetBoolField(trigger, "disableAllWeather");
		bool boolField5 = ReflectionUtil.GetBoolField(trigger, "enableCurrentLevelWeather");
		bool boolField6 = ReflectionUtil.GetBoolField(trigger, "setInElevatorTrigger");
		object fieldObject = ReflectionUtil.GetFieldObject(trigger, "reverbPreset");
		object fieldObject2 = ReflectionUtil.GetFieldObject(trigger, "audioChanges");
		int num2 = CountEnumerable(fieldObject2);
		if (boolField)
		{
			num -= 150f;
		}
		if (boolField6)
		{
			num -= 80f;
		}
		if (boolField5)
		{
			num -= 80f;
		}
		if (boolField2)
		{
			num += 80f;
		}
		if (boolField3)
		{
			num += 80f;
		}
		if (boolField4)
		{
			num += 80f;
		}
		if (fieldObject != null)
		{
			num += 25f;
		}
		if (num2 > 0)
		{
			num += 15f;
		}
		if (text.Contains("inside") || text2.Contains("inside"))
		{
			num += 80f;
		}
		if (text.Contains("interior") || text.Contains("factory") || text.Contains("dungeon") || text.Contains("facility"))
		{
			num += 35f;
		}
		if (text.Contains("ambience") || text2.Contains("ambience"))
		{
			num += 35f;
		}
		if (text.Contains("outside") || text2.Contains("outside"))
		{
			num -= 120f;
		}
		if (text.Contains("hangar") || text2.Contains("hangar") || text.Contains("ship") || text2.Contains("ship"))
		{
			num -= 120f;
		}
		if (text.Contains("wind") || text2.Contains("wind") || text.Contains("weather") || text2.Contains("weather"))
		{
			num -= 60f;
		}
		if (text.Contains("elevator") || text2.Contains("elevator"))
		{
			num -= 45f;
		}
		if ((Object)(object)((Component)trigger).gameObject != (Object)null && ((Component)trigger).gameObject.activeInHierarchy)
		{
			num += 15f;
		}
		float num3 = Vector3.Distance(((Component)trigger).transform.position, playerPosition);
		if (num3 < tieRadius)
		{
			num += Mathf.Clamp(10f - num3 * 0.15f, 0f, 10f);
		}
		return num;
	}

	private int CountEnumerable(object value)
	{
		if (value == null)
		{
			return 0;
		}
		if (value is Array array)
		{
			return array.Length;
		}
		if (value is ICollection collection)
		{
			return collection.Count;
		}
		if (!(value is IEnumerable enumerable))
		{
			return 0;
		}
		int num = 0;
		foreach (object item in enumerable)
		{
			num++;
			if (num > 999)
			{
				break;
			}
		}
		return num;
	}

	private void RefreshInsideTimeAndLighting()
	{
		try
		{
			if ((Object)(object)TimeOfDay.Instance != (Object)null)
			{
				ReflectionUtil.SetBoolField(TimeOfDay.Instance, "insideLighting", value: true);
				ReflectionUtil.CallFlexibleMethod(TimeOfDay.Instance, "SetInsideLightingDimness", new object[3] { true, 1f, 0f });
			}
		}
		catch
		{
		}
	}

	private void TrySetClockVisible(bool visible)
	{
		try
		{
			HUDManager val = Object.FindObjectOfType<HUDManager>();
			if ((Object)(object)val != (Object)null)
			{
				ReflectionUtil.CallFlexibleMethod(val, "SetClockVisible", new object[1] { visible });
			}
		}
		catch
		{
		}
	}

	private void MaintainInsideStateIfNeeded()
	{
		if (Time.time > maintainInsideStateUntil)
		{
			return;
		}
		PlayerControllerB[] playersToMove = GetPlayersToMove();
		PlayerControllerB[] array = playersToMove;
		foreach (PlayerControllerB val in array)
		{
			if (!((Object)(object)val == (Object)null) && val.isPlayerControlled && !val.isPlayerDead)
			{
				SetPlayerInsideFactoryFields(val);
				ApplyLocalInsideVisualState(val);
			}
		}
	}

	private ulong GetPlayerClientIdSafeUlong(PlayerControllerB player)
	{
		ulong uLongField = ReflectionUtil.GetULongField(player, "playerClientId");
		if (uLongField == 0)
		{
			uLongField = ReflectionUtil.GetULongField(player, "actualClientId");
		}
		return uLongField;
	}

	private int GetPlayerClientIdSafe(PlayerControllerB player)
	{
		int intField = ReflectionUtil.GetIntField(player, "playerClientId");
		if (intField == 0)
		{
			intField = ReflectionUtil.GetIntField(player, "actualClientId");
		}
		return intField;
	}

	private void DoorTip(string header, string body, bool warning)
	{
		try
		{
			HUDManager val = Object.FindObjectOfType<HUDManager>();
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			MethodInfo method = typeof(HUDManager).GetMethod("DisplayTip", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (method == null)
			{
				return;
			}
			ParameterInfo[] parameters = method.GetParameters();
			object[] array = new object[parameters.Length];
			int num = 0;
			for (int i = 0; i < parameters.Length; i++)
			{
				Type parameterType = parameters[i].ParameterType;
				if (parameterType == typeof(string))
				{
					array[i] = num switch
					{
						1 => body, 
						0 => header, 
						_ => "FacilityStartTeleport", 
					};
					num++;
				}
				else if (parameterType == typeof(bool))
				{
					array[i] = warning;
				}
				else
				{
					array[i] = GetDefaultValue(parameterType);
				}
			}
			method.Invoke(val, array);
		}
		catch
		{
		}
	}

	private string GetTransformPath(Transform transform)
	{
		if ((Object)(object)transform == (Object)null)
		{
			return "";
		}
		string text = ((Object)transform).name;
		Transform parent = transform.parent;
		while ((Object)(object)parent != (Object)null)
		{
			text = ((Object)parent).name + "/" + text;
			parent = parent.parent;
		}
		return text;
	}
}
internal static class ReflectionUtil
{
	public static object GetFieldObject(object instance, string fieldName)
	{
		try
		{
			if (instance == null)
			{
				return null;
			}
			FieldInfo field = instance.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field == null)
			{
				return null;
			}
			return field.GetValue(instance);
		}
		catch
		{
			return null;
		}
	}

	public static Transform GetTransformField(object instance, string fieldName)
	{
		object fieldObject = GetFieldObject(instance, fieldName);
		return (Transform)((fieldObject is Transform) ? fieldObject : null);
	}

	public static void SetFieldObject(object instance, string fieldName, object value)
	{
		try
		{
			if (instance != null)
			{
				FieldInfo field = instance.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (!(field == null) && (value == null || field.FieldType.IsAssignableFrom(value.GetType())))
				{
					field.SetValue(instance, value);
				}
			}
		}
		catch
		{
		}
	}

	public static bool GetBoolField(object instance, string fieldName)
	{
		try
		{
			object fieldObject = GetFieldObject(instance, fieldName);
			if (fieldObject is bool)
			{
				return (bool)fieldObject;
			}
		}
		catch
		{
		}
		return false;
	}

	public static void SetBoolField(object instance, string fieldName, bool value)
	{
		try
		{
			if (instance != null)
			{
				FieldInfo field = instance.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (!(field == null) && !(field.FieldType != typeof(bool)))
				{
					field.SetValue(instance, value);
				}
			}
		}
		catch
		{
		}
	}

	public static void SetIntField(object instance, string fieldName, int value)
	{
		try
		{
			if (instance == null)
			{
				return;
			}
			FieldInfo field = instance.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (!(field == null))
			{
				if (field.FieldType == typeof(int))
				{
					field.SetValue(instance, value);
				}
				else if (field.FieldType == typeof(uint))
				{
					field.SetValue(instance, (uint)value);
				}
			}
		}
		catch
		{
		}
	}

	public static int GetIntField(object instance, string fieldName)
	{
		try
		{
			object fieldObject = GetFieldObject(instance, fieldName);
			if (fieldObject is int result)
			{
				return result;
			}
			if (fieldObject is long)
			{
				return (int)(long)fieldObject;
			}
			if (fieldObject is ulong)
			{
				return (int)(ulong)fieldObject;
			}
			if (fieldObject is uint)
			{
				return (int)(uint)fieldObject;
			}
		}
		catch
		{
		}
		return 0;
	}

	public static ulong GetULongField(object instance, string fieldName)
	{
		try
		{
			object fieldObject = GetFieldObject(instance, fieldName);
			if (fieldObject is ulong result)
			{
				return result;
			}
			if (fieldObject is ulong result2)
			{
				return result2;
			}
			if (fieldObject is uint)
			{
				return (uint)fieldObject;
			}
			if (fieldObject is int)
			{
				return (ulong)(int)fieldObject;
			}
		}
		catch
		{
		}
		return 0uL;
	}

	public static string GetStringField(object instance, string fieldName)
	{
		try
		{
			object fieldObject = GetFieldObject(instance, fieldName);
			if (fieldObject is string)
			{
				return (string)fieldObject;
			}
		}
		catch
		{
		}
		return "";
	}

	public static bool CallNoArgMethod(object instance, string methodName)
	{
		object obj = CallNoArgMethodReturn(instance, methodName);
		return obj != null;
	}

	public static object CallNoArgMethodReturn(object instance, string methodName)
	{
		try
		{
			if (instance == null)
			{
				return null;
			}
			MethodInfo method = instance.GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
			if (method == null)
			{
				return null;
			}
			return method.Invoke(instance, null);
		}
		catch
		{
			return null;
		}
	}

	public static bool CallFlexibleMethod(object instance, string methodName, object[] preferredArgs)
	{
		try
		{
			if (instance == null)
			{
				return false;
			}
			MethodInfo[] methods = instance.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			MethodInfo[] array = methods;
			foreach (MethodInfo methodInfo in array)
			{
				if (methodInfo.Name != methodName)
				{
					continue;
				}
				ParameterInfo[] parameters = methodInfo.GetParameters();
				object[] array2 = new object[parameters.Length];
				for (int j = 0; j < parameters.Length; j++)
				{
					Type parameterType = parameters[j].ParameterType;
					object obj = null;
					bool flag = false;
					if (preferredArgs != null)
					{
						foreach (object obj2 in preferredArgs)
						{
							if (obj2 != null)
							{
								if (parameterType.IsAssignableFrom(obj2.GetType()))
								{
									obj = obj2;
									flag = true;
									break;
								}
								if (parameterType == typeof(int) && obj2 is int)
								{
									obj = obj2;
									flag = true;
									break;
								}
								if (parameterType == typeof(ulong) && obj2 is ulong)
								{
									obj = obj2;
									flag = true;
									break;
								}
								if (parameterType == typeof(ulong) && obj2 is int)
								{
									obj = (ulong)(int)obj2;
									flag = true;
									break;
								}
								if (parameterType == typeof(uint) && obj2 is int)
								{
									obj = (uint)(int)obj2;
									flag = true;
									break;
								}
								if (parameterType == typeof(bool) && obj2 is bool)
								{
									obj = obj2;
									flag = true;
									break;
								}
							}
						}
					}
					array2[j] = (flag ? obj : GetDefaultValue(parameterType));
				}
				methodInfo.Invoke(instance, array2);
				return true;
			}
		}
		catch
		{
		}
		return false;
	}

	private static object GetDefaultValue(Type type)
	{
		if (type == null)
		{
			return null;
		}
		if (type.IsByRef)
		{
			type = type.GetElementType();
		}
		if (type.IsValueType)
		{
			return Activator.CreateInstance(type);
		}
		return null;
	}

	public static void SetFieldOnBoxedStruct(ref object boxedStruct, string fieldName, object value)
	{
		try
		{
			if (boxedStruct != null)
			{
				FieldInfo field = boxedStruct.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (!(field == null))
				{
					field.SetValue(boxedStruct, value);
				}
			}
		}
		catch
		{
		}
	}
}

plugins/CChanges/RandomSuit.dll

Decompiled 8 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using GameNetcodeStuff;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("ScrapVisbility")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ScrapVisbility")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("8a6853bd-bdc9-4741-95c7-5aa2c8c6a6f9")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace RandomStartSuit;

[BepInPlugin("YourFurnace.RandomStartSuit", "RandomStartSuit", "1.0.6")]
public class Plugin : BaseUnityPlugin
{
	private struct Assignment
	{
		public ulong clientId;

		public int playerIndex;

		public int suitId;

		public float resendUntil;

		public float nextResend;

		public float repairUntil;

		public float nextRepair;
	}

	public const string PluginGuid = "YourFurnace.RandomStartSuit";

	public const string PluginName = "RandomStartSuit";

	public const string PluginVersion = "1.0.6";

	private const string MessageName = "YourFurnace.RandomStartSuit.ApplySuit.v1";

	private const BindingFlags AnyFlags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;

	private ConfigEntry<string> allowedSuitsCsv;

	private ConfigEntry<float> firstAssignmentDelay;

	private ConfigEntry<float> rescanInterval;

	private ConfigEntry<float> serverResendSeconds;

	private ConfigEntry<float> serverResendInterval;

	private ConfigEntry<float> clientRepairSeconds;

	private ConfigEntry<float> clientRepairInterval;

	private ConfigEntry<bool> requireActiveSuitRackObject;

	private ConfigEntry<bool> onlyAssignInShipLobby;

	private ConfigEntry<bool> useVanillaClientRpcAlso;

	private ConfigEntry<bool> logDebug;

	private readonly Dictionary<ulong, Assignment> assignmentsByClientId = new Dictionary<ulong, Assignment>();

	private readonly Dictionary<ulong, Assignment> clientRepairsByClientId = new Dictionary<ulong, Assignment>();

	private readonly Random serverRandom = new Random();

	private StartOfRound lastStartOfRound;

	private int lastStartOfRoundInstanceId = -1;

	private string lastSceneName = string.Empty;

	private float nextScanTime;

	private bool hasSeenNoStartOfRound = true;

	private bool messageHandlerRegistered;

	private float nextMessageRegisterTry;

	private void Awake()
	{
		allowedSuitsCsv = ((BaseUnityPlugin)this).Config.Bind<string>("Suit Selection", "Allowed suit names", "FemaleBlue,FemaleClothed,FemaleLime,FemaleOrange,FemalePink,FemaleStar,RealMan", "Comma separated suit names. Matching is case insensitive and ignores spaces, dashes, underscores, and punctuation. Use ALL to allow every active suit rack suit.");
		firstAssignmentDelay = ((BaseUnityPlugin)this).Config.Bind<float>("Assignment", "First assignment delay seconds", 1f, "How long to wait after a lobby/player manager appears before choosing random suits.");
		rescanInterval = ((BaseUnityPlugin)this).Config.Bind<float>("Assignment", "Rescan interval seconds", 1f, "How often the host checks for newly joined players that still need a suit.");
		onlyAssignInShipLobby = ((BaseUnityPlugin)this).Config.Bind<bool>("Assignment", "Only assign while in ship lobby", true, "Recommended true. Stops the mod from assigning or resending while loading levels, leaving a game, or returning to main menu.");
		requireActiveSuitRackObject = ((BaseUnityPlugin)this).Config.Bind<bool>("Compatibility", "Require active suit rack object", true, "Recommended true. Only chooses real active UnlockableSuit objects that the suit mods spawned.");
		useVanillaClientRpcAlso = ((BaseUnityPlugin)this).Config.Bind<bool>("Networking", "Also call vanilla ClientRpc", true, "Keeps vanilla suit syncing for other clients. This mod also sends its own local repair message so the owning client sees its own suit.");
		serverResendSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Networking", "Server resend seconds", 15f, "How long the host resends the chosen suit through the custom message. This beats other suit mods that set default suit shortly after joining.");
		serverResendInterval = ((BaseUnityPlugin)this).Config.Bind<float>("Networking", "Server resend interval seconds", 1f, "How often the host resends the chosen suit during the resend window.");
		clientRepairSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Client Repair", "Client local repair seconds", 18f, "How long each client locally reapplies received suit assignments. This fixes the owner seeing their own suit as default.");
		clientRepairInterval = ((BaseUnityPlugin)this).Config.Bind<float>("Client Repair", "Client local repair interval seconds", 1f, "How often each client locally reapplies received suit assignments.");
		logDebug = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "Log debug info", true, "Logs chosen suits, network messages, and local repair applies.");
		SceneManager.sceneLoaded += OnSceneLoaded;
		TryRegisterMessageHandler();
		((BaseUnityPlugin)this).Logger.LogInfo((object)"RandomStartSuit 1.0.6 loaded. Owner-client repair suit sync enabled.");
	}

	private void OnDestroy()
	{
		SceneManager.sceneLoaded -= OnSceneLoaded;
		UnregisterMessageHandler();
	}

	private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
	{
		string text = ((Scene)(ref scene)).name ?? string.Empty;
		if (IsMenuScene(text))
		{
			assignmentsByClientId.Clear();
			clientRepairsByClientId.Clear();
			nextScanTime = 0f;
			if (logDebug.Value)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)("RandomStartSuit cleared assignments on scene load: " + text));
			}
		}
	}

	private void Update()
	{
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			TryRegisterMessageHandler();
			ApplyClientRepairs();
			Scene activeScene = SceneManager.GetActiveScene();
			string text = ((Scene)(ref activeScene)).name ?? string.Empty;
			if (IsMenuScene(text))
			{
				return;
			}
			if ((Object)(object)StartOfRound.Instance == (Object)null)
			{
				if (!hasSeenNoStartOfRound)
				{
					ResetSession("StartOfRound became null");
				}
				hasSeenNoStartOfRound = true;
				lastStartOfRound = null;
				lastStartOfRoundInstanceId = -1;
				lastSceneName = text;
				return;
			}
			hasSeenNoStartOfRound = false;
			int instanceID = ((Object)StartOfRound.Instance).GetInstanceID();
			if ((Object)(object)StartOfRound.Instance != (Object)(object)lastStartOfRound || instanceID != lastStartOfRoundInstanceId || text != lastSceneName)
			{
				lastStartOfRound = StartOfRound.Instance;
				lastStartOfRoundInstanceId = instanceID;
				lastSceneName = text;
				ResetSession("new StartOfRound/session/scene detected");
				nextScanTime = Time.realtimeSinceStartup + Mathf.Max(0.25f, firstAssignmentDelay.Value);
			}
			if (IsServerOrHost() && IsNetworkActive() && (!onlyAssignInShipLobby.Value || IsSafeLobbyTime()))
			{
				if (Time.realtimeSinceStartup >= nextScanTime)
				{
					nextScanTime = Time.realtimeSinceStartup + Mathf.Max(0.5f, rescanInterval.Value);
					AssignMissingPlayers();
				}
				ResendAssignments();
			}
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)("RandomStartSuit Update error: " + ex.GetType().Name + ": " + ex.Message));
		}
	}

	private void ResetSession(string reason)
	{
		assignmentsByClientId.Clear();
		clientRepairsByClientId.Clear();
		nextScanTime = Time.realtimeSinceStartup + Mathf.Max(0.25f, firstAssignmentDelay.Value);
		if (logDebug.Value)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)("RandomStartSuit reset assignment state: " + reason));
		}
	}

	private bool IsMenuScene(string sceneName)
	{
		if (string.IsNullOrEmpty(sceneName))
		{
			return false;
		}
		return sceneName.IndexOf("menu", StringComparison.OrdinalIgnoreCase) >= 0 || sceneName.IndexOf("init", StringComparison.OrdinalIgnoreCase) >= 0;
	}

	private bool IsSafeLobbyTime()
	{
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			StartOfRound instance = StartOfRound.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				return false;
			}
			if (!instance.inShipPhase)
			{
				return false;
			}
			if (instance.shipHasLanded || instance.shipIsLeaving)
			{
				return false;
			}
			Scene activeScene = SceneManager.GetActiveScene();
			string sceneName = ((Scene)(ref activeScene)).name ?? string.Empty;
			if (IsMenuScene(sceneName))
			{
				return false;
			}
			return true;
		}
		catch
		{
			return false;
		}
	}

	private void AssignMissingPlayers()
	{
		if ((Object)(object)StartOfRound.Instance == (Object)null || StartOfRound.Instance.allPlayerScripts == null)
		{
			return;
		}
		List<UnlockableSuit> allowedSuits = GetAllowedSuits();
		if (allowedSuits.Count == 0)
		{
			if (logDebug.Value)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("RandomStartSuit found no allowed suits. Config: " + allowedSuitsCsv.Value));
			}
			return;
		}
		PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
		for (int i = 0; i < allPlayerScripts.Length; i++)
		{
			PlayerControllerB player = allPlayerScripts[i];
			if (!IsRealControlledPlayer(player))
			{
				continue;
			}
			ulong playerClientId = GetPlayerClientId(player, (ulong)i);
			if (assignmentsByClientId.ContainsKey(playerClientId))
			{
				continue;
			}
			UnlockableSuit suit = allowedSuits[serverRandom.Next(allowedSuits.Count)];
			int suitId = GetSuitId(suit);
			if (suitId >= 0)
			{
				ApplySuitLocalOnly(suit, player, i, playerClientId, suitId, playAudio: true, "host initial");
				Assignment assignment = default(Assignment);
				assignment.clientId = playerClientId;
				assignment.playerIndex = i;
				assignment.suitId = suitId;
				assignment.resendUntil = Time.realtimeSinceStartup + Mathf.Max(1f, serverResendSeconds.Value);
				assignment.nextResend = Time.realtimeSinceStartup;
				assignment.repairUntil = Time.realtimeSinceStartup + Mathf.Max(1f, clientRepairSeconds.Value);
				assignment.nextRepair = Time.realtimeSinceStartup;
				Assignment assignment2 = assignment;
				assignmentsByClientId[playerClientId] = assignment2;
				clientRepairsByClientId[playerClientId] = assignment2;
				if (useVanillaClientRpcAlso.Value)
				{
					CallVanillaClientRpc(suit, i, playerClientId);
				}
				SendAssignmentToAllClients(assignment2);
				if (logDebug.Value)
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)("RandomStartSuit assigned " + PlayerLabel(player, i) + " clientId=" + playerClientId + " suitID=" + suitId + " suit=" + GetSuitDisplayName(suit)));
				}
			}
		}
	}

	private void ResendAssignments()
	{
		if (assignmentsByClientId.Count == 0 || !IsNetworkActive())
		{
			return;
		}
		float realtimeSinceStartup = Time.realtimeSinceStartup;
		List<ulong> list = assignmentsByClientId.Keys.ToList();
		for (int i = 0; i < list.Count; i++)
		{
			Assignment assignment = assignmentsByClientId[list[i]];
			if (realtimeSinceStartup > assignment.resendUntil || realtimeSinceStartup < assignment.nextResend)
			{
				continue;
			}
			assignment.nextResend = realtimeSinceStartup + Mathf.Max(0.25f, serverResendInterval.Value);
			assignmentsByClientId[list[i]] = assignment;
			PlayerControllerB val = FindPlayerByClientIdOrIndex(assignment.clientId, assignment.playerIndex);
			UnlockableSuit val2 = FindSuitById(assignment.suitId);
			if ((Object)(object)val != (Object)null && (Object)(object)val2 != (Object)null)
			{
				ApplySuitLocalOnly(val2, val, assignment.playerIndex, assignment.clientId, assignment.suitId, playAudio: false, "host resend local");
				if (useVanillaClientRpcAlso.Value)
				{
					CallVanillaClientRpc(val2, assignment.playerIndex, assignment.clientId);
				}
			}
			SendAssignmentToAllClients(assignment);
			if (logDebug.Value)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)("RandomStartSuit resent suitID=" + assignment.suitId + " for clientId=" + assignment.clientId + " playerIndex=" + assignment.playerIndex));
			}
		}
	}

	private void TryRegisterMessageHandler()
	{
		//IL_0074: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Expected O, but got Unknown
		if (messageHandlerRegistered || Time.realtimeSinceStartup < nextMessageRegisterTry)
		{
			return;
		}
		nextMessageRegisterTry = Time.realtimeSinceStartup + 1f;
		try
		{
			if (!((Object)(object)NetworkManager.Singleton == (Object)null) && NetworkManager.Singleton.CustomMessagingManager != null)
			{
				NetworkManager.Singleton.CustomMessagingManager.RegisterNamedMessageHandler("YourFurnace.RandomStartSuit.ApplySuit.v1", new HandleNamedMessageDelegate(OnReceiveAssignmentMessage));
				messageHandlerRegistered = true;
				if (logDebug.Value)
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)"RandomStartSuit registered custom suit sync message handler.");
				}
			}
		}
		catch (Exception ex)
		{
			if (logDebug.Value)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("RandomStartSuit could not register message handler yet: " + ex.GetType().Name + ": " + ex.Message));
			}
		}
	}

	private void UnregisterMessageHandler()
	{
		if (!messageHandlerRegistered)
		{
			return;
		}
		try
		{
			if ((Object)(object)NetworkManager.Singleton != (Object)null && NetworkManager.Singleton.CustomMessagingManager != null)
			{
				NetworkManager.Singleton.CustomMessagingManager.UnregisterNamedMessageHandler("YourFurnace.RandomStartSuit.ApplySuit.v1");
			}
		}
		catch
		{
		}
		messageHandlerRegistered = false;
	}

	private void SendAssignmentToAllClients(Assignment assignment)
	{
		//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: 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_0092: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if (!IsServerOrHost() || !IsNetworkActive())
			{
				return;
			}
			NetworkManager singleton = NetworkManager.Singleton;
			if ((Object)(object)singleton == (Object)null || singleton.CustomMessagingManager == null)
			{
				return;
			}
			FastBufferWriter val = default(FastBufferWriter);
			((FastBufferWriter)(ref val))..ctor(32, (Allocator)2, -1);
			try
			{
				((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref assignment.clientId, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref assignment.playerIndex, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref assignment.suitId, default(ForPrimitives));
				IReadOnlyList<ulong> connectedClientsIds = singleton.ConnectedClientsIds;
				for (int i = 0; i < connectedClientsIds.Count; i++)
				{
					try
					{
						singleton.CustomMessagingManager.SendNamedMessage("YourFurnace.RandomStartSuit.ApplySuit.v1", connectedClientsIds[i], val, (NetworkDelivery)3);
					}
					catch (Exception ex)
					{
						if (logDebug.Value)
						{
							((BaseUnityPlugin)this).Logger.LogWarning((object)("RandomStartSuit failed sending custom suit message to client " + connectedClientsIds[i] + ": " + ex.GetType().Name + ": " + ex.Message));
						}
					}
				}
			}
			finally
			{
				((IDisposable)(FastBufferWriter)(ref val)).Dispose();
			}
		}
		catch (Exception ex2)
		{
			if (logDebug.Value)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("RandomStartSuit SendAssignmentToAllClients error: " + ex2.GetType().Name + ": " + ex2.Message));
			}
		}
	}

	private void OnReceiveAssignmentMessage(ulong senderClientId, FastBufferReader reader)
	{
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			ulong num = default(ulong);
			((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref num, default(ForPrimitives));
			int playerIndex = default(int);
			((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref playerIndex, default(ForPrimitives));
			int suitId = default(int);
			((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref suitId, default(ForPrimitives));
			Assignment assignment = default(Assignment);
			assignment.clientId = num;
			assignment.playerIndex = playerIndex;
			assignment.suitId = suitId;
			assignment.repairUntil = Time.realtimeSinceStartup + Mathf.Max(1f, clientRepairSeconds.Value);
			assignment.nextRepair = Time.realtimeSinceStartup;
			Assignment assignment2 = assignment;
			clientRepairsByClientId[num] = assignment2;
			if (logDebug.Value)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)("RandomStartSuit received custom suit assignment from " + senderClientId + ": targetClientId=" + num + " playerIndex=" + playerIndex + " suitId=" + suitId));
			}
			ApplyOneClientRepair(assignment2, immediate: true);
		}
		catch (Exception ex)
		{
			if (logDebug.Value)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("RandomStartSuit receive message error: " + ex.GetType().Name + ": " + ex.Message));
			}
		}
	}

	private void ApplyClientRepairs()
	{
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		if (clientRepairsByClientId.Count == 0 || (Object)(object)StartOfRound.Instance == (Object)null)
		{
			return;
		}
		Scene activeScene = SceneManager.GetActiveScene();
		string sceneName = ((Scene)(ref activeScene)).name ?? string.Empty;
		if (IsMenuScene(sceneName))
		{
			return;
		}
		float realtimeSinceStartup = Time.realtimeSinceStartup;
		List<ulong> list = clientRepairsByClientId.Keys.ToList();
		for (int i = 0; i < list.Count; i++)
		{
			Assignment assignment = clientRepairsByClientId[list[i]];
			if (realtimeSinceStartup > assignment.repairUntil)
			{
				clientRepairsByClientId.Remove(list[i]);
			}
			else if (!(realtimeSinceStartup < assignment.nextRepair))
			{
				assignment.nextRepair = realtimeSinceStartup + Mathf.Max(0.25f, clientRepairInterval.Value);
				clientRepairsByClientId[list[i]] = assignment;
				ApplyOneClientRepair(assignment, immediate: false);
			}
		}
	}

	private void ApplyOneClientRepair(Assignment a, bool immediate)
	{
		try
		{
			UnlockableSuit val = FindSuitById(a.suitId);
			PlayerControllerB val2 = FindPlayerByClientIdOrIndex(a.clientId, a.playerIndex);
			if (!((Object)(object)val == (Object)null) && !((Object)(object)val2 == (Object)null))
			{
				ApplySuitLocalOnly(val, val2, a.playerIndex, a.clientId, a.suitId, playAudio: false, immediate ? "client immediate repair" : "client timed repair");
			}
		}
		catch (Exception ex)
		{
			if (logDebug.Value)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("RandomStartSuit client repair failed: " + ex.GetType().Name + ": " + ex.Message));
			}
		}
	}

	private void ApplySuitLocalOnly(UnlockableSuit suit, PlayerControllerB player, int playerIndex, ulong clientId, int suitId, bool playAudio, string reason)
	{
		if (!((Object)(object)suit == (Object)null) && !((Object)(object)player == (Object)null) && suitId >= 0)
		{
			SetSuitStateFields(player, suitId);
			Type type = ((object)suit).GetType();
			InvokeMatchingMethods(suit, type, "SwitchSuitForPlayer", new object[3] { player, suitId, playAudio });
			InvokeMatchingMethods(suit, type, "SwitchSuitForPlayer", new object[2] { player, suitId });
			InvokeMatchingMethods(suit, type, "SwitchSuitForPlayer", new object[1] { player });
			SetSuitStateFields(player, suitId);
			if (logDebug.Value)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)("RandomStartSuit local apply " + reason + " -> " + PlayerLabel(player, playerIndex) + " clientId=" + clientId + " suit=" + GetSuitDisplayName(suit)));
			}
		}
	}

	private void CallVanillaClientRpc(UnlockableSuit suit, int playerIndex, ulong clientId)
	{
		if (!((Object)(object)suit == (Object)null))
		{
			Type type = ((object)suit).GetType();
			InvokeMatchingMethods(suit, type, "SwitchSuitClientRpc", new object[1] { playerIndex });
			if ((ulong)playerIndex != clientId)
			{
				InvokeMatchingMethods(suit, type, "SwitchSuitClientRpc", new object[1] { (int)clientId });
			}
		}
	}

	private PlayerControllerB FindPlayerByClientIdOrIndex(ulong clientId, int playerIndex)
	{
		try
		{
			if ((Object)(object)StartOfRound.Instance == (Object)null || StartOfRound.Instance.allPlayerScripts == null)
			{
				return null;
			}
			PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
			for (int i = 0; i < allPlayerScripts.Length; i++)
			{
				PlayerControllerB val = allPlayerScripts[i];
				if (!((Object)(object)val == (Object)null) && GetPlayerClientId(val, (ulong)i) == clientId)
				{
					return val;
				}
			}
			if (playerIndex >= 0 && playerIndex < allPlayerScripts.Length)
			{
				return allPlayerScripts[playerIndex];
			}
		}
		catch
		{
		}
		return null;
	}

	private List<UnlockableSuit> GetAllowedSuits()
	{
		UnlockableSuit[] array = Object.FindObjectsOfType<UnlockableSuit>(true);
		List<UnlockableSuit> list = new List<UnlockableSuit>();
		if (array == null || array.Length == 0)
		{
			return list;
		}
		List<string> list2 = ParseWantedSuitNames(allowedSuitsCsv.Value);
		bool flag = list2.Count == 0 || list2.Contains("all") || list2.Contains("*");
		foreach (UnlockableSuit val in array)
		{
			if (!((Object)(object)val == (Object)null) && (!requireActiveSuitRackObject.Value || ((Component)val).gameObject.activeInHierarchy))
			{
				int suitId = GetSuitId(val);
				if (suitId >= 0 && (flag || MatchesAnyWantedSuit(val, list2)))
				{
					list.Add(val);
				}
			}
		}
		Dictionary<int, UnlockableSuit> dictionary = new Dictionary<int, UnlockableSuit>();
		for (int j = 0; j < list.Count; j++)
		{
			int suitId2 = GetSuitId(list[j]);
			if (suitId2 >= 0 && !dictionary.ContainsKey(suitId2))
			{
				dictionary.Add(suitId2, list[j]);
			}
		}
		return dictionary.Values.ToList();
	}

	private UnlockableSuit FindSuitById(int suitId)
	{
		UnlockableSuit[] array = Object.FindObjectsOfType<UnlockableSuit>(true);
		if (array == null)
		{
			return null;
		}
		foreach (UnlockableSuit val in array)
		{
			if (!((Object)(object)val == (Object)null) && (!requireActiveSuitRackObject.Value || ((Component)val).gameObject.activeInHierarchy) && GetSuitId(val) == suitId)
			{
				return val;
			}
		}
		return null;
	}

	private List<string> ParseWantedSuitNames(string csv)
	{
		List<string> list = new List<string>();
		if (string.IsNullOrWhiteSpace(csv))
		{
			return list;
		}
		string[] array = csv.Split(new char[1] { ',' });
		for (int i = 0; i < array.Length; i++)
		{
			string text = Normalize(array[i]);
			if (!string.IsNullOrEmpty(text))
			{
				list.Add(text);
			}
		}
		return list;
	}

	private bool MatchesAnyWantedSuit(UnlockableSuit suit, List<string> wanted)
	{
		if (wanted == null || wanted.Count == 0)
		{
			return true;
		}
		List<string> suitNameCandidates = GetSuitNameCandidates(suit);
		for (int i = 0; i < suitNameCandidates.Count; i++)
		{
			string text = Normalize(suitNameCandidates[i]);
			if (string.IsNullOrEmpty(text))
			{
				continue;
			}
			for (int j = 0; j < wanted.Count; j++)
			{
				if (text == wanted[j] || text.Contains(wanted[j]) || wanted[j].Contains(text))
				{
					return true;
				}
			}
		}
		return false;
	}

	private List<string> GetSuitNameCandidates(UnlockableSuit suit)
	{
		List<string> list = new List<string>();
		if ((Object)(object)suit == (Object)null)
		{
			return list;
		}
		list.Add(((Object)suit).name);
		list.Add(((Object)((Component)suit).gameObject).name);
		int suitId = GetSuitId(suit);
		string unlockableNameById = GetUnlockableNameById(suitId);
		if (!string.IsNullOrEmpty(unlockableNameById))
		{
			list.Add(unlockableNameById);
		}
		object memberValue = GetMemberValue(suit, "suitMaterial", null);
		Object val = (Object)((memberValue is Object) ? memberValue : null);
		if (val != (Object)null)
		{
			list.Add(val.name);
		}
		return list;
	}

	private string GetSuitDisplayName(UnlockableSuit suit)
	{
		if ((Object)(object)suit == (Object)null)
		{
			return "null";
		}
		int suitId = GetSuitId(suit);
		string unlockableNameById = GetUnlockableNameById(suitId);
		if (!string.IsNullOrEmpty(unlockableNameById))
		{
			return unlockableNameById + " [id " + suitId + "]";
		}
		return ((Object)((Component)suit).gameObject).name + " [id " + suitId + "]";
	}

	private string GetUnlockableNameById(int id)
	{
		try
		{
			if (id < 0 || (Object)(object)StartOfRound.Instance == (Object)null)
			{
				return null;
			}
			object memberValue = GetMemberValue(StartOfRound.Instance, "unlockablesList", null);
			object memberValue2 = GetMemberValue(memberValue, "unlockables", null);
			if (!(memberValue2 is IEnumerable enumerable))
			{
				return null;
			}
			int num = 0;
			foreach (object item in enumerable)
			{
				if (num == id)
				{
					return GetMemberValue(item, "unlockableName", null)?.ToString();
				}
				num++;
			}
		}
		catch
		{
		}
		return null;
	}

	private int GetSuitId(UnlockableSuit suit)
	{
		object memberValue = GetMemberValue(suit, "suitID", null);
		if (memberValue == null)
		{
			memberValue = GetMemberValue(suit, "syncedSuitID", null);
		}
		try
		{
			if (memberValue == null)
			{
				return -1;
			}
			return Convert.ToInt32(memberValue, CultureInfo.InvariantCulture);
		}
		catch
		{
			return -1;
		}
	}

	private void SetSuitStateFields(PlayerControllerB player, int suitId)
	{
		if (!((Object)(object)player == (Object)null) && suitId >= 0)
		{
			SetMemberValue(player, "currentSuitID", suitId);
			SetMemberValue(player, "currentSuitId", suitId);
			SetMemberValue(player, "syncedSuitID", suitId);
			SetMemberValue(player, "syncedSuitId", suitId);
		}
	}

	private bool InvokeMatchingMethods(object instance, Type type, string methodName, object[] args)
	{
		if (instance == null || type == null)
		{
			return false;
		}
		bool result = false;
		try
		{
			MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (MethodInfo methodInfo in methods)
			{
				if (methodInfo.Name != methodName)
				{
					continue;
				}
				ParameterInfo[] parameters = methodInfo.GetParameters();
				if (parameters.Length != args.Length)
				{
					continue;
				}
				object[] array = new object[args.Length];
				bool flag = true;
				for (int j = 0; j < args.Length; j++)
				{
					if (!TryConvertArg(args[j], parameters[j].ParameterType, out array[j]))
					{
						flag = false;
						break;
					}
				}
				if (!flag)
				{
					continue;
				}
				try
				{
					methodInfo.Invoke(instance, array);
					result = true;
					if (logDebug.Value && methodName.IndexOf("Rpc", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						((BaseUnityPlugin)this).Logger.LogInfo((object)("RandomStartSuit called " + methodName + "(" + ArgsToString(array) + ") on " + GetSuitDisplayName((UnlockableSuit)((instance is UnlockableSuit) ? instance : null))));
					}
				}
				catch (Exception ex)
				{
					if (logDebug.Value)
					{
						((BaseUnityPlugin)this).Logger.LogWarning((object)("RandomStartSuit invoke failed for " + methodName + ": " + ShortException(ex)));
					}
				}
			}
		}
		catch (Exception ex2)
		{
			if (logDebug.Value)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("RandomStartSuit invoke scan failed for " + methodName + ": " + ex2.Message));
			}
		}
		return result;
	}

	private string ArgsToString(object[] args)
	{
		if (args == null || args.Length == 0)
		{
			return string.Empty;
		}
		string[] array = new string[args.Length];
		for (int i = 0; i < args.Length; i++)
		{
			array[i] = ((args[i] == null) ? "null" : args[i].ToString());
		}
		return string.Join(",", array);
	}

	private string ShortException(Exception ex)
	{
		if (ex == null)
		{
			return "null";
		}
		if (ex.InnerException != null)
		{
			return ex.InnerException.GetType().Name + ": " + ex.InnerException.Message;
		}
		return ex.GetType().Name + ": " + ex.Message;
	}

	private bool TryConvertArg(object value, Type targetType, out object converted)
	{
		converted = null;
		try
		{
			if (value == null)
			{
				converted = null;
				return !targetType.IsValueType || Nullable.GetUnderlyingType(targetType) != null;
			}
			Type type = value.GetType();
			if (targetType.IsAssignableFrom(type))
			{
				converted = value;
				return true;
			}
			if (targetType == typeof(int))
			{
				converted = Convert.ToInt32(value, CultureInfo.InvariantCulture);
				return true;
			}
			if (targetType == typeof(ulong))
			{
				converted = Convert.ToUInt64(value, CultureInfo.InvariantCulture);
				return true;
			}
			if (targetType == typeof(uint))
			{
				converted = Convert.ToUInt32(value, CultureInfo.InvariantCulture);
				return true;
			}
			if (targetType == typeof(long))
			{
				converted = Convert.ToInt64(value, CultureInfo.InvariantCulture);
				return true;
			}
			if (targetType == typeof(bool))
			{
				converted = Convert.ToBoolean(value, CultureInfo.InvariantCulture);
				return true;
			}
			converted = Convert.ChangeType(value, targetType, CultureInfo.InvariantCulture);
			return true;
		}
		catch
		{
			return false;
		}
	}

	private bool IsRealControlledPlayer(PlayerControllerB player)
	{
		if ((Object)(object)player == (Object)null)
		{
			return false;
		}
		try
		{
			if (!((Component)player).gameObject.activeInHierarchy)
			{
				return false;
			}
			if (!player.isPlayerControlled)
			{
				return false;
			}
			if (player.isPlayerDead)
			{
				return false;
			}
			return true;
		}
		catch
		{
			return false;
		}
	}

	private ulong GetPlayerClientId(PlayerControllerB player, ulong fallback)
	{
		object memberValue = GetMemberValue(player, "playerClientId", null);
		if (memberValue == null)
		{
			memberValue = GetMemberValue(player, "actualClientId", null);
		}
		try
		{
			if (memberValue != null)
			{
				return Convert.ToUInt64(memberValue, CultureInfo.InvariantCulture);
			}
		}
		catch
		{
		}
		return fallback;
	}

	private bool IsServerOrHost()
	{
		try
		{
			if ((Object)(object)NetworkManager.Singleton != (Object)null)
			{
				return NetworkManager.Singleton.IsServer || NetworkManager.Singleton.IsHost;
			}
		}
		catch
		{
		}
		try
		{
			object memberValue = GetMemberValue(StartOfRound.Instance, "IsServer", null);
			object memberValue2 = GetMemberValue(StartOfRound.Instance, "IsHost", null);
			if (memberValue is int num && num != 0)
			{
				return true;
			}
			if (memberValue2 is bool && (bool)memberValue2)
			{
				return true;
			}
		}
		catch
		{
		}
		return false;
	}

	private bool IsNetworkActive()
	{
		try
		{
			if ((Object)(object)NetworkManager.Singleton == (Object)null)
			{
				return false;
			}
			if (!NetworkManager.Singleton.IsListening)
			{
				return false;
			}
			if (GetMemberValue(NetworkManager.Singleton, "ShutdownInProgress", false) is int num && num != 0)
			{
				return false;
			}
			return true;
		}
		catch
		{
			return false;
		}
	}

	private object GetMemberValue(object target, string name, object fallback)
	{
		if (target == null || string.IsNullOrEmpty(name))
		{
			return fallback;
		}
		try
		{
			Type type = target as Type;
			object obj = target;
			if (type == null)
			{
				type = target.GetType();
			}
			else
			{
				obj = null;
			}
			FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			if (field != null)
			{
				return field.GetValue(obj);
			}
			PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			if (property != null && property.GetIndexParameters().Length == 0)
			{
				return property.GetValue(obj, null);
			}
		}
		catch
		{
		}
		return fallback;
	}

	private bool SetMemberValue(object target, string name, object value)
	{
		if (target == null || string.IsNullOrEmpty(name))
		{
			return false;
		}
		try
		{
			Type type = target.GetType();
			FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			if (field != null && TryConvertArg(value, field.FieldType, out var converted))
			{
				field.SetValue(target, converted);
				return true;
			}
			PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			if (property != null && property.CanWrite && property.GetIndexParameters().Length == 0 && TryConvertArg(value, property.PropertyType, out var converted2))
			{
				property.SetValue(target, converted2, null);
				return true;
			}
		}
		catch
		{
		}
		return false;
	}

	private string Normalize(string text)
	{
		if (string.IsNullOrEmpty(text))
		{
			return string.Empty;
		}
		char[] array = text.ToLowerInvariant().ToCharArray();
		StringBuilder stringBuilder = new StringBuilder(array.Length);
		foreach (char c in array)
		{
			if (char.IsLetterOrDigit(c))
			{
				stringBuilder.Append(c);
			}
		}
		return stringBuilder.ToString();
	}

	private string PlayerLabel(PlayerControllerB player, int index)
	{
		if ((Object)(object)player == (Object)null)
		{
			return "null";
		}
		string text = GetMemberValue(player, "playerUsername", null) as string;
		if (!string.IsNullOrEmpty(text))
		{
			return text + "[" + index + "]";
		}
		return ((Object)player).name + "[" + index + "]";
	}
}

plugins/CChanges/ScrapVisbility.dll

Decompiled 8 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using UnityEngine;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("ScrapVisbility")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ScrapVisbility")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("8a6853bd-bdc9-4741-95c7-5aa2c8c6a6f9")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace ScrapVisibility;

[BepInPlugin("YourFurnace.ScrapVisibility", "ScrapVisibility", "1.8.3")]
public class ScrapVisibility : BaseUnityPlugin
{
	private const string modGUID = "YourFurnace.ScrapVisibility";

	private const string modName = "ScrapVisibility";

	private const string modVersion = "1.8.3";

	private readonly Harmony harmony = new Harmony("YourFurnace.ScrapVisibility");

	internal static ScrapVisibility Instance;

	internal static ManualLogSource Log;

	internal static ConfigEntry<bool> DisableManualRightClickScan;

	internal static ConfigEntry<bool> ShowModelGlow;

	internal static ConfigEntry<bool> ShowText;

	internal static ConfigEntry<bool> ShowLight;

	internal static ConfigEntry<bool> HideTextBehindWalls;

	internal static ConfigEntry<float> MaxDistance;

	internal static ConfigEntry<float> RefreshInterval;

	internal static ConfigEntry<float> TintStrength;

	internal static ConfigEntry<float> EmissionStrength;

	internal static ConfigEntry<float> TextSize;

	internal static ConfigEntry<float> TextHeightOffset;

	internal static ConfigEntry<float> LightIntensity;

	internal static ConfigEntry<float> LightRange;

	internal static ConfigEntry<float> PulseSpeed;

	internal static ConfigEntry<float> TextOcclusionPadding;

	internal static ConfigEntry<float> ScreenEdgeMargin;

	internal static ConfigEntry<float> TextVisibilityGraceTime;

	private static Transform textRoot;

	private float nextRefreshTime = 0f;

	internal static Transform GetTextRoot()
	{
		//IL_007d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Expected O, but got Unknown
		//IL_0093: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: 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)
		if ((Object)(object)textRoot != (Object)null)
		{
			return textRoot;
		}
		GameObject val = GameObject.Find("ScrapVisibility_TextRoot");
		if ((Object)(object)val != (Object)null)
		{
			textRoot = val.transform;
			textRoot.position = Vector3.zero;
			textRoot.rotation = Quaternion.identity;
			textRoot.localScale = Vector3.one;
			return textRoot;
		}
		GameObject val2 = new GameObject("ScrapVisibility_TextRoot");
		textRoot = val2.transform;
		textRoot.position = Vector3.zero;
		textRoot.rotation = Quaternion.identity;
		textRoot.localScale = Vector3.one;
		return textRoot;
	}

	private void Awake()
	{
		Instance = this;
		Log = ((BaseUnityPlugin)this).Logger;
		DisableManualRightClickScan = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Disable manual right click scan", true, "If true, normal right click scan is blocked.");
		ShowModelGlow = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "Show model glow", true, "Tints the real item model.");
		ShowText = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "Show 3D text", true, "Show item name and value above items.");
		ShowLight = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "Show apparatus style light", true, "Adds a real 3D point light to items.");
		HideTextBehindWalls = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "Hide text behind walls", true, "If true, text label hides when the item itself is blocked by walls.");
		MaxDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Visibility", "Max display distance", 120f, "Maximum distance for item highlights and labels.");
		RefreshInterval = ((BaseUnityPlugin)this).Config.Bind<float>("Performance", "Refresh interval", 1f, "How often the mod searches for items.");
		TintStrength = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "Tint strength", 1f, "How strongly the model gets tinted.");
		EmissionStrength = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "Emission strength", 5.5f, "How strongly the material emission is pushed.");
		TextSize = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "Text size", 0.022f, "Base size of the 3D text above items.");
		TextHeightOffset = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "Text height offset", 0.38f, "How far above the item the text floats.");
		LightIntensity = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "Light intensity", 6f, "Base brightness of the apparatus style light.");
		LightRange = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "Light range", 6f, "Base range of the apparatus style light.");
		PulseSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "Pulse speed", 2.8f, "How fast the glow pulses.");
		TextOcclusionPadding = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "Text occlusion padding", 0.12f, "How much of the end of the ray to ignore when checking if the item is blocked.");
		ScreenEdgeMargin = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "Screen edge margin", 0.12f, "Extra margin around the screen so text still shows near the edge/peripheral view.");
		TextVisibilityGraceTime = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "Text visibility grace time", 0.2f, "How long text stays visible after one bad raycast. Helps stop flicker while moving.");
		harmony.PatchAll();
		Log.LogInfo((object)"ScrapVisibility loaded. Stable neutral labels plus normal glow strength enabled.");
	}

	private void OnDestroy()
	{
		harmony.UnpatchSelf();
	}

	private void Update()
	{
		if (!(Time.time < nextRefreshTime))
		{
			nextRefreshTime = Time.time + Mathf.Max(0.2f, RefreshInterval.Value);
			AttachHighlightersToItems();
		}
	}

	private void AttachHighlightersToItems()
	{
		GrabbableObject[] array = Object.FindObjectsOfType<GrabbableObject>();
		GrabbableObject[] array2 = array;
		foreach (GrabbableObject val in array2)
		{
			if (!((Object)(object)val == (Object)null) && !((Object)(object)val.itemProperties == (Object)null) && (Object)(object)((Component)val).GetComponent<ItemValueHighlighter>() == (Object)null)
			{
				ItemValueHighlighter itemValueHighlighter = ((Component)val).gameObject.AddComponent<ItemValueHighlighter>();
				itemValueHighlighter.Init(val);
			}
		}
	}

	internal static Color GetDisplayColor(bool isScrap, int value)
	{
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0081: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
		if (!isScrap)
		{
			return new Color(0.2f, 0.55f, 1f, 1f);
		}
		if (value >= 300)
		{
			return new Color(1f, 0.78f, 0.05f, 1f);
		}
		if (value >= 150)
		{
			return new Color(0.72f, 0.25f, 1f, 1f);
		}
		if (value >= 100)
		{
			return new Color(0.15f, 1f, 0.25f, 1f);
		}
		if (value >= 50)
		{
			return new Color(1f, 1f, 0.15f, 1f);
		}
		return new Color(1f, 0.45f, 0.05f, 1f);
	}
}
internal class ItemValueHighlighter : MonoBehaviour
{
	private GrabbableObject item;

	private GameObject textObject;

	private TextMesh textMesh;

	private MeshRenderer textRenderer;

	private Material textMaterial;

	private GameObject lightObject;

	private Light glowLight;

	private readonly List<Renderer> targetRenderers = new List<Renderer>();

	private readonly Dictionary<Renderer, MaterialPropertyBlock> blocks = new Dictionary<Renderer, MaterialPropertyBlock>();

	private int lastValue = -999;

	private string lastName = "";

	private Color lastColor = Color.white;

	private bool textVisible = true;

	private float lastGoodTextVisibleTime = 0f;

	private static readonly FieldInfo fieldIsHeld = AccessTools.Field(typeof(GrabbableObject), "isHeld");

	private static readonly FieldInfo fieldIsPocketed = AccessTools.Field(typeof(GrabbableObject), "isPocketed");

	private static readonly FieldInfo fieldIsHeldByEnemy = AccessTools.Field(typeof(GrabbableObject), "isHeldByEnemy");

	private static readonly FieldInfo fieldPlayerHeldBy = AccessTools.Field(typeof(GrabbableObject), "playerHeldBy");

	private static readonly FieldInfo fieldCurrentlyHeldObjectServer = AccessTools.Field(typeof(PlayerControllerB), "currentlyHeldObjectServer");

	private static readonly FieldInfo fieldCurrentlyHeldObject = AccessTools.Field(typeof(PlayerControllerB), "currentlyHeldObject");

	public void Init(GrabbableObject target)
	{
		item = target;
		CacheTargetRenderers();
		CreateText();
		CreateApparatusLight();
		SetVisualsActive(active: false);
	}

	private void CacheTargetRenderers()
	{
		//IL_007a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0084: Expected O, but got Unknown
		targetRenderers.Clear();
		blocks.Clear();
		Renderer[] componentsInChildren = ((Component)item).GetComponentsInChildren<Renderer>(true);
		Renderer[] array = componentsInChildren;
		foreach (Renderer val in array)
		{
			if (!((Object)(object)val == (Object)null))
			{
				string lowerName = ((Object)((Component)val).gameObject).name.ToLowerInvariant();
				if (!ShouldSkipRenderer(val, lowerName))
				{
					targetRenderers.Add(val);
					blocks[val] = new MaterialPropertyBlock();
				}
			}
		}
	}

	private bool ShouldSkipRenderer(Renderer renderer, string lowerName)
	{
		if ((Object)(object)renderer == (Object)null)
		{
			return true;
		}
		if (!renderer.enabled)
		{
			return true;
		}
		if (string.IsNullOrEmpty(lowerName))
		{
			lowerName = ((Object)((Component)renderer).gameObject).name.ToLowerInvariant();
		}
		string text = ((object)renderer).GetType().Name.ToLowerInvariant();
		if (text.Contains("particle") || text.Contains("trail") || text.Contains("line"))
		{
			return true;
		}
		if (lowerName.Contains("scan") || lowerName.Contains("scannode") || lowerName.Contains("scan node") || lowerName.Contains("trigger") || lowerName.Contains("collider") || lowerName.Contains("collision") || lowerName.Contains("hitbox") || lowerName.Contains("interact") || lowerName.Contains("scrapvisibility") || lowerName.Contains("mapdot") || lowerName.Contains("radar") || lowerName.Contains("audio") || lowerName.Contains("sound") || lowerName.Contains("light") || lowerName.Contains("vfx") || lowerName.Contains("sfx"))
		{
			return true;
		}
		return false;
	}

	private void CreateText()
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Expected O, but got Unknown
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_018b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0195: Expected O, but got Unknown
		//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ea: Expected O, but got Unknown
		//IL_0283: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b1: Unknown result type (might be due to invalid IL or missing references)
		textObject = new GameObject("ScrapVisibility_3DText");
		textObject.transform.SetParent(ScrapVisibility.GetTextRoot(), false);
		textObject.transform.position = ((Component)this).transform.position + Vector3.up * 0.5f;
		textObject.transform.rotation = Quaternion.identity;
		textObject.transform.localScale = Vector3.one;
		textMesh = textObject.AddComponent<TextMesh>();
		textMesh.text = "";
		textMesh.alignment = (TextAlignment)1;
		textMesh.anchor = (TextAnchor)4;
		textMesh.fontSize = 90;
		textMesh.characterSize = 0.022f;
		textMesh.color = Color.white;
		Font builtinResource = Resources.GetBuiltinResource<Font>("Arial.ttf");
		if ((Object)(object)builtinResource != (Object)null)
		{
			textMesh.font = builtinResource;
		}
		textRenderer = textObject.GetComponent<MeshRenderer>();
		if ((Object)(object)textRenderer == (Object)null)
		{
			textRenderer = textObject.AddComponent<MeshRenderer>();
		}
		if ((Object)(object)textMesh.font != (Object)null && (Object)(object)textMesh.font.material != (Object)null)
		{
			textMaterial = new Material(textMesh.font.material);
		}
		else
		{
			Shader val = Shader.Find("GUI/Text Shader");
			if ((Object)(object)val == (Object)null)
			{
				val = Shader.Find("Unlit/Transparent");
			}
			if ((Object)(object)val == (Object)null)
			{
				val = Shader.Find("Sprites/Default");
			}
			textMaterial = new Material(val);
		}
		((Object)textMaterial).name = "ScrapVisibility_ReadableTextMaterial";
		textMaterial.renderQueue = 3000;
		if (textMaterial.HasProperty("_Cull"))
		{
			textMaterial.SetInt("_Cull", 0);
		}
		if (textMaterial.HasProperty("_ZWrite"))
		{
			textMaterial.SetInt("_ZWrite", 0);
		}
		if (textMaterial.HasProperty("_Color"))
		{
			textMaterial.SetColor("_Color", Color.white);
		}
		if (textMaterial.HasProperty("_FaceColor"))
		{
			textMaterial.SetColor("_FaceColor", Color.white);
		}
		((Renderer)textRenderer).sharedMaterial = textMaterial;
		((Renderer)textRenderer).shadowCastingMode = (ShadowCastingMode)0;
		((Renderer)textRenderer).receiveShadows = false;
	}

	private void CreateApparatusLight()
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Expected O, but got Unknown
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		lightObject = new GameObject("ScrapVisibility_ApparatusStyleLight");
		lightObject.transform.SetParent(((Component)this).transform, false);
		lightObject.transform.localPosition = Vector3.zero;
		glowLight = lightObject.AddComponent<Light>();
		glowLight.type = (LightType)2;
		glowLight.color = Color.white;
		glowLight.intensity = 6f;
		glowLight.range = 6f;
		((Behaviour)glowLight).enabled = false;
		glowLight.shadows = (LightShadows)1;
		glowLight.renderMode = (LightRenderMode)1;
		glowLight.cullingMask = -1;
		glowLight.bounceIntensity = 1.2f;
	}

	private void LateUpdate()
	{
		//IL_00fc: 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_013e: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)item == (Object)null)
		{
			DestroySelf();
			return;
		}
		if ((Object)(object)item.itemProperties == (Object)null)
		{
			ClearGlow();
			SetVisualsActive(active: false);
			return;
		}
		PlayerControllerB localPlayer = GetLocalPlayer();
		if ((Object)(object)localPlayer == (Object)null || !localPlayer.isPlayerControlled || localPlayer.isPlayerDead)
		{
			ClearGlow();
			SetVisualsActive(active: false);
			return;
		}
		if (IsHeldByAnyone(localPlayer))
		{
			ClearGlow();
			SetVisualsActive(active: false);
			return;
		}
		if (!((Component)item).gameObject.activeInHierarchy)
		{
			ClearGlow();
			SetVisualsActive(active: false);
			return;
		}
		if (!TryGetBounds(out var bounds))
		{
			ClearGlow();
			SetVisualsActive(active: false);
			return;
		}
		float num = Vector3.Distance(((Component)localPlayer).transform.position, ((Bounds)(ref bounds)).center);
		if (ScrapVisibility.MaxDistance != null && num > ScrapVisibility.MaxDistance.Value)
		{
			ClearGlow();
			SetVisualsActive(active: false);
		}
		else
		{
			UpdateVisuals(bounds, num);
			SetVisualsActive(active: true);
		}
	}

	private PlayerControllerB GetLocalPlayer()
	{
		if ((Object)(object)GameNetworkManager.Instance == (Object)null)
		{
			return null;
		}
		return GameNetworkManager.Instance.localPlayerController;
	}

	private bool IsHeldByAnyone(PlayerControllerB localPlayer)
	{
		if (GetBoolField(fieldIsHeld))
		{
			return true;
		}
		if (GetBoolField(fieldIsPocketed))
		{
			return true;
		}
		if (GetBoolField(fieldIsHeldByEnemy))
		{
			return true;
		}
		object objectField = GetObjectField(fieldPlayerHeldBy);
		if (objectField != null)
		{
			return true;
		}
		if ((Object)(object)localPlayer != (Object)null)
		{
			object playerObjectField = GetPlayerObjectField(localPlayer, fieldCurrentlyHeldObjectServer);
			object playerObjectField2 = GetPlayerObjectField(localPlayer, fieldCurrentlyHeldObject);
			if (playerObjectField == item || playerObjectField2 == item)
			{
				return true;
			}
		}
		Transform parent = ((Component)item).transform.parent;
		if ((Object)(object)parent != (Object)null)
		{
			string text = ((Object)parent).name.ToLowerInvariant();
			if (text.Contains("player") || text.Contains("hand") || text.Contains("hold") || text.Contains("itemholder") || text.Contains("pocket"))
			{
				return true;
			}
		}
		return false;
	}

	private bool GetBoolField(FieldInfo field)
	{
		try
		{
			if (field == null)
			{
				return false;
			}
			object value = field.GetValue(item);
			if (value is bool)
			{
				return (bool)value;
			}
		}
		catch
		{
		}
		return false;
	}

	private object GetObjectField(FieldInfo field)
	{
		try
		{
			if (field == null)
			{
				return null;
			}
			return field.GetValue(item);
		}
		catch
		{
		}
		return null;
	}

	private object GetPlayerObjectField(PlayerControllerB player, FieldInfo field)
	{
		try
		{
			if (field == null || (Object)(object)player == (Object)null)
			{
				return null;
			}
			return field.GetValue(player);
		}
		catch
		{
		}
		return null;
	}

	private bool TryGetBounds(out Bounds bounds)
	{
		//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_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_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)
		bounds = new Bounds(((Component)this).transform.position, Vector3.one * 0.25f);
		bool flag = false;
		foreach (Renderer targetRenderer in targetRenderers)
		{
			if ((Object)(object)targetRenderer == (Object)null)
			{
				continue;
			}
			string lowerName = ((Object)((Component)targetRenderer).gameObject).name.ToLowerInvariant();
			if (!ShouldSkipRenderer(targetRenderer, lowerName) && ((Component)targetRenderer).gameObject.activeInHierarchy)
			{
				if (!flag)
				{
					bounds = targetRenderer.bounds;
					flag = true;
				}
				else
				{
					((Bounds)(ref bounds)).Encapsulate(targetRenderer.bounds);
				}
			}
		}
		return flag;
	}

	private void UpdateVisuals(Bounds bounds, float distance)
	{
		//IL_0089: Unknown result type (might be due to invalid IL or missing references)
		//IL_008e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cd: 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_00db: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ef: 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_0110: Unknown result type (might be due to invalid IL or missing references)
		//IL_0112: Unknown result type (might be due to invalid IL or missing references)
		//IL_0189: Unknown result type (might be due to invalid IL or missing references)
		//IL_018c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0196: Unknown result type (might be due to invalid IL or missing references)
		//IL_0198: Unknown result type (might be due to invalid IL or missing references)
		//IL_0135: Unknown result type (might be due to invalid IL or missing references)
		//IL_0136: Unknown result type (might be due to invalid IL or missing references)
		bool flag = (Object)(object)item.itemProperties != (Object)null && item.itemProperties.isScrap;
		int num = Mathf.Max(0, item.scrapValue);
		string text = "Item";
		if ((Object)(object)item.itemProperties != (Object)null && !string.IsNullOrEmpty(item.itemProperties.itemName))
		{
			text = item.itemProperties.itemName;
		}
		Color displayColor = ScrapVisibility.GetDisplayColor(flag, num);
		float num2 = 0.78f + Mathf.Sin(Time.time * GetPulseSpeed()) * 0.22f;
		Color tintColor = Color.Lerp(Color.white, displayColor, GetTintStrength());
		tintColor.a = 1f;
		Color emissionColor = displayColor * GetEmissionStrength() * num2;
		emissionColor.a = 1f;
		ApplyGlow(tintColor, emissionColor);
		if (num != lastValue || text != lastName || displayColor != lastColor)
		{
			lastValue = num;
			lastName = text;
			lastColor = displayColor;
			if ((Object)(object)textMesh != (Object)null)
			{
				if (flag)
				{
					textMesh.text = text + "\n$" + num;
				}
				else
				{
					textMesh.text = text;
				}
			}
		}
		UpdateApparatusLight(bounds, flag, num, displayColor, num2);
		UpdateText(bounds, distance, displayColor);
	}

	private void UpdateApparatusLight(Bounds bounds, bool isScrap, int value, Color baseColor, float pulse)
	{
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)glowLight == (Object)null))
		{
			float lightMultiplierForItem = GetLightMultiplierForItem(isScrap, value);
			((Component)glowLight).transform.position = ((Bounds)(ref bounds)).center;
			glowLight.color = baseColor;
			glowLight.intensity = GetLightIntensity() * lightMultiplierForItem * pulse;
			glowLight.range = GetLightRange() * lightMultiplierForItem;
			glowLight.bounceIntensity = 1.5f + lightMultiplierForItem * 0.35f;
		}
	}

	private float GetLightMultiplierForItem(bool isScrap, int value)
	{
		if (!isScrap)
		{
			return 1.25f;
		}
		if (value >= 300)
		{
			return 2.25f;
		}
		if (value >= 150)
		{
			return 1.8f;
		}
		if (value >= 100)
		{
			return 1.45f;
		}
		if (value >= 50)
		{
			return 1.15f;
		}
		return 0.9f;
	}

	private void ApplyGlow(Color tintColor, Color emissionColor)
	{
		//IL_006c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_0093: Unknown result type (might be due to invalid IL or missing references)
		if (ScrapVisibility.ShowModelGlow == null || !ScrapVisibility.ShowModelGlow.Value)
		{
			ClearGlow();
			return;
		}
		foreach (Renderer targetRenderer in targetRenderers)
		{
			if (!((Object)(object)targetRenderer == (Object)null))
			{
				MaterialPropertyBlock val = blocks[targetRenderer];
				targetRenderer.GetPropertyBlock(val);
				val.SetColor("_Color", tintColor);
				val.SetColor("_BaseColor", tintColor);
				val.SetColor("_EmissionColor", emissionColor);
				val.SetColor("_EmissiveColor", emissionColor);
				targetRenderer.SetPropertyBlock(val);
			}
		}
	}

	private void ClearGlow()
	{
		foreach (Renderer targetRenderer in targetRenderers)
		{
			if (!((Object)(object)targetRenderer == (Object)null))
			{
				targetRenderer.SetPropertyBlock((MaterialPropertyBlock)null);
			}
		}
	}

	private void UpdateText(Bounds bounds, float distance, Color color)
	{
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_006a: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_009a: Unknown result type (might be due to invalid IL or missing references)
		//IL_011d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0147: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)textObject == (Object)null || (Object)(object)textMesh == (Object)null)
		{
			return;
		}
		Transform textRoot = ScrapVisibility.GetTextRoot();
		if ((Object)(object)textObject.transform.parent != (Object)(object)textRoot)
		{
			textObject.transform.SetParent(textRoot, true);
		}
		textObject.transform.position = GetStableLabelPosition(bounds);
		Camera main = Camera.main;
		if ((Object)(object)main != (Object)null)
		{
			textObject.transform.rotation = ((Component)main).transform.rotation;
		}
		textVisible = IsObjectVisibleForText(bounds);
		textMesh.characterSize = GetTextSize();
		textObject.transform.localScale = Vector3.one;
		textMesh.color = color;
		if ((Object)(object)textMaterial != (Object)null)
		{
			if (textMaterial.HasProperty("_Color"))
			{
				textMaterial.SetColor("_Color", color);
			}
			if (textMaterial.HasProperty("_FaceColor"))
			{
				textMaterial.SetColor("_FaceColor", color);
			}
		}
	}

	private Vector3 GetStableLabelPosition(Bounds bounds)
	{
		//IL_0003: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: 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_00aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0094: Unknown result type (might be due to invalid IL or missing references)
		//IL_009e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00af: Unknown result type (might be due to invalid IL or missing references)
		Vector3 val = ((Bounds)(ref bounds)).center;
		float num = Mathf.Clamp(((Bounds)(ref bounds)).size.y, 0.15f, 3f);
		float y = ((Bounds)(ref bounds)).max.y;
		float num2 = GetTextHeightOffset() + Mathf.Clamp(num * 0.15f, 0.04f, 0.3f);
		val.y = y + num2;
		if (float.IsNaN(val.x) || float.IsNaN(val.y) || float.IsNaN(val.z))
		{
			val = ((Component)this).transform.position + Vector3.up * 0.6f;
		}
		return val;
	}

	private Vector3 GetParentScaleCompensatedLocalScale(float desiredWorldScale)
	{
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: 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_0062: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: 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)
		Transform val = (((Object)(object)textObject != (Object)null) ? textObject.transform.parent : null);
		if ((Object)(object)val == (Object)null)
		{
			return Vector3.one * desiredWorldScale;
		}
		Vector3 lossyScale = val.lossyScale;
		return new Vector3(desiredWorldScale / SafeSignedScale(lossyScale.x), desiredWorldScale / SafeSignedScale(lossyScale.y), desiredWorldScale / SafeSignedScale(lossyScale.z));
	}

	private float SafeSignedScale(float value)
	{
		if (Mathf.Abs(value) < 0.001f)
		{
			return (value < 0f) ? (-0.001f) : 0.001f;
		}
		return value;
	}

	private bool IsObjectVisibleForText(Bounds bounds)
	{
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: 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_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_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_0097: Unknown result type (might be due to invalid IL or missing references)
		//IL_009c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ca: 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_00db: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e5: 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_00f7: 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_0107: Unknown result type (might be due to invalid IL or missing references)
		//IL_010e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0119: Unknown result type (might be due to invalid IL or missing references)
		//IL_011f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0124: Unknown result type (might be due to invalid IL or missing references)
		//IL_0129: Unknown result type (might be due to invalid IL or missing references)
		//IL_0130: Unknown result type (might be due to invalid IL or missing references)
		//IL_0131: 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_013d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0143: Unknown result type (might be due to invalid IL or missing references)
		//IL_0148: Unknown result type (might be due to invalid IL or missing references)
		//IL_014d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0154: Unknown result type (might be due to invalid IL or missing references)
		//IL_0155: Unknown result type (might be due to invalid IL or missing references)
		//IL_015c: 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_0168: Unknown result type (might be due to invalid IL or missing references)
		//IL_016d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0172: 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_017b: 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_0187: Unknown result type (might be due to invalid IL or missing references)
		//IL_018e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0193: Unknown result type (might be due to invalid IL or missing references)
		//IL_0198: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a8: 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_01b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01db: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0202: Unknown result type (might be due to invalid IL or missing references)
		//IL_0207: 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_0214: Unknown result type (might be due to invalid IL or missing references)
		//IL_0215: Unknown result type (might be due to invalid IL or missing references)
		//IL_021b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0222: Unknown result type (might be due to invalid IL or missing references)
		//IL_0229: Unknown result type (might be due to invalid IL or missing references)
		//IL_022e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0233: Unknown result type (might be due to invalid IL or missing references)
		//IL_023b: Unknown result type (might be due to invalid IL or missing references)
		//IL_023c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0243: Unknown result type (might be due to invalid IL or missing references)
		//IL_024a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0251: Unknown result type (might be due to invalid IL or missing references)
		//IL_0256: Unknown result type (might be due to invalid IL or missing references)
		//IL_025b: Unknown result type (might be due to invalid IL or missing references)
		//IL_026c: Unknown result type (might be due to invalid IL or missing references)
		if (ScrapVisibility.HideTextBehindWalls == null || !ScrapVisibility.HideTextBehindWalls.Value)
		{
			return true;
		}
		Camera main = Camera.main;
		if ((Object)(object)main == (Object)null)
		{
			return true;
		}
		Vector3 center = ((Bounds)(ref bounds)).center;
		Vector3 extents = ((Bounds)(ref bounds)).extents;
		Vector3[] array = (Vector3[])(object)new Vector3[15]
		{
			center,
			center + new Vector3(0f, extents.y, 0f),
			center - new Vector3(0f, extents.y, 0f),
			center + new Vector3(extents.x, 0f, 0f),
			center - new Vector3(extents.x, 0f, 0f),
			center + new Vector3(0f, 0f, extents.z),
			center - new Vector3(0f, 0f, extents.z),
			center + new Vector3(extents.x, extents.y, extents.z),
			center + new Vector3(0f - extents.x, extents.y, extents.z),
			center + new Vector3(extents.x, extents.y, 0f - extents.z),
			center + new Vector3(0f - extents.x, extents.y, 0f - extents.z),
			center + new Vector3(extents.x, 0f - extents.y, extents.z),
			center + new Vector3(0f - extents.x, 0f - extents.y, extents.z),
			center + new Vector3(extents.x, 0f - extents.y, 0f - extents.z),
			center + new Vector3(0f - extents.x, 0f - extents.y, 0f - extents.z)
		};
		for (int i = 0; i < array.Length; i++)
		{
			if (PointIsOnScreenAndNotBlocked(main, array[i]))
			{
				lastGoodTextVisibleTime = Time.time;
				return true;
			}
		}
		float num = 0.2f;
		if (ScrapVisibility.TextVisibilityGraceTime != null)
		{
			num = Mathf.Clamp(ScrapVisibility.TextVisibilityGraceTime.Value, 0f, 1f);
		}
		if (Time.time - lastGoodTextVisibleTime < num)
		{
			return true;
		}
		return false;
	}

	private bool PointIsOnScreenAndNotBlocked(Camera cam, Vector3 targetPosition)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0003: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		//IL_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		//IL_008d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0101: Unknown result type (might be due to invalid IL or missing references)
		//IL_0145: 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_01ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
		Vector3 val = cam.WorldToViewportPoint(targetPosition);
		if (val.z <= 0f)
		{
			return false;
		}
		float num = 0.12f;
		if (ScrapVisibility.ScreenEdgeMargin != null)
		{
			num = Mathf.Clamp(ScrapVisibility.ScreenEdgeMargin.Value, 0f, 0.35f);
		}
		if (val.x < 0f - num || val.x > 1f + num)
		{
			return false;
		}
		if (val.y < 0f - num || val.y > 1f + num)
		{
			return false;
		}
		Vector3 position = ((Component)cam).transform.position;
		Vector3 val2 = targetPosition - position;
		float magnitude = ((Vector3)(ref val2)).magnitude;
		if (magnitude <= 0.05f)
		{
			return true;
		}
		Vector3 normalized = ((Vector3)(ref val2)).normalized;
		position += normalized * 0.25f;
		float num2 = 0.12f;
		if (ScrapVisibility.TextOcclusionPadding != null)
		{
			num2 = Mathf.Clamp(ScrapVisibility.TextOcclusionPadding.Value, 0.01f, 1f);
		}
		float num3 = Mathf.Max(0.05f, magnitude - num2);
		RaycastHit[] array = Physics.RaycastAll(position, normalized, num3, -1, (QueryTriggerInteraction)1);
		if (array == null || array.Length == 0)
		{
			return true;
		}
		Array.Sort(array, (RaycastHit a, RaycastHit b) => ((RaycastHit)(ref a)).distance.CompareTo(((RaycastHit)(ref b)).distance));
		PlayerControllerB localPlayer = GetLocalPlayer();
		for (int i = 0; i < array.Length; i++)
		{
			RaycastHit val3 = array[i];
			if ((Object)(object)((RaycastHit)(ref val3)).collider == (Object)null)
			{
				continue;
			}
			Transform transform = ((Component)((RaycastHit)(ref val3)).collider).transform;
			if ((Object)(object)textObject != (Object)null && transform.IsChildOf(textObject.transform))
			{
				continue;
			}
			if (transform.IsChildOf(((Component)item).transform))
			{
				return true;
			}
			GrabbableObject componentInParent = ((Component)((RaycastHit)(ref val3)).collider).GetComponentInParent<GrabbableObject>();
			if ((Object)(object)componentInParent == (Object)(object)item)
			{
				return true;
			}
			if ((!((Object)(object)localPlayer != (Object)null) || !transform.IsChildOf(((Component)localPlayer).transform)) && !((Object)(object)componentInParent != (Object)null))
			{
				string text = ((Object)transform).name.ToLowerInvariant();
				if (!text.Contains("player") && !text.Contains("camera") && !text.Contains("hand") && !text.Contains("itemholder") && !text.Contains("held") && !text.Contains("helmet") && !text.Contains("scan") && !text.Contains("trigger"))
				{
					return false;
				}
			}
		}
		return true;
	}

	private void SetVisualsActive(bool active)
	{
		bool flag = active && textVisible && ScrapVisibility.ShowText != null && ScrapVisibility.ShowText.Value;
		bool enabled = active && ScrapVisibility.ShowLight != null && ScrapVisibility.ShowLight.Value;
		if ((Object)(object)textObject != (Object)null && textObject.activeSelf != flag)
		{
			textObject.SetActive(flag);
		}
		if ((Object)(object)glowLight != (Object)null)
		{
			((Behaviour)glowLight).enabled = enabled;
		}
	}

	private float GetTintStrength()
	{
		if (ScrapVisibility.TintStrength == null)
		{
			return 1f;
		}
		return Mathf.Clamp01(ScrapVisibility.TintStrength.Value);
	}

	private float GetEmissionStrength()
	{
		if (ScrapVisibility.EmissionStrength == null)
		{
			return 5.5f;
		}
		return Mathf.Clamp(ScrapVisibility.EmissionStrength.Value, 0f, 12f);
	}

	private float GetPulseSpeed()
	{
		if (ScrapVisibility.PulseSpeed == null)
		{
			return 2.8f;
		}
		return Mathf.Max(0f, ScrapVisibility.PulseSpeed.Value);
	}

	private float GetLightIntensity()
	{
		if (ScrapVisibility.LightIntensity == null)
		{
			return 6f;
		}
		return Mathf.Clamp(ScrapVisibility.LightIntensity.Value, 0f, 30f);
	}

	private float GetLightRange()
	{
		if (ScrapVisibility.LightRange == null)
		{
			return 6f;
		}
		return Mathf.Clamp(ScrapVisibility.LightRange.Value, 0f, 20f);
	}

	private float GetTextSize()
	{
		if (ScrapVisibility.TextSize == null)
		{
			return 0.022f;
		}
		return Mathf.Clamp(ScrapVisibility.TextSize.Value, 0.005f, 0.14f);
	}

	private float GetTextHeightOffset()
	{
		if (ScrapVisibility.TextHeightOffset == null)
		{
			return 0.22f;
		}
		return Mathf.Clamp(ScrapVisibility.TextHeightOffset.Value, 0f, 2f);
	}

	private void DestroySelf()
	{
		ClearGlow();
		if ((Object)(object)textObject != (Object)null)
		{
			Object.Destroy((Object)(object)textObject);
			textObject = null;
		}
		if ((Object)(object)lightObject != (Object)null)
		{
			Object.Destroy((Object)(object)lightObject);
			lightObject = null;
		}
		if ((Object)(object)textMaterial != (Object)null)
		{
			Object.Destroy((Object)(object)textMaterial);
			textMaterial = null;
		}
		Object.Destroy((Object)(object)this);
	}

	private void OnDestroy()
	{
		ClearGlow();
		if ((Object)(object)textObject != (Object)null)
		{
			Object.Destroy((Object)(object)textObject);
		}
		if ((Object)(object)lightObject != (Object)null)
		{
			Object.Destroy((Object)(object)lightObject);
		}
		if ((Object)(object)textMaterial != (Object)null)
		{
			Object.Destroy((Object)(object)textMaterial);
		}
	}
}
[HarmonyPatch(typeof(HUDManager), "PingScan_performed")]
internal static class DisableManualScannerPatch
{
	private static bool Prefix()
	{
		if (ScrapVisibility.DisableManualRightClickScan != null && ScrapVisibility.DisableManualRightClickScan.Value)
		{
			return false;
		}
		return true;
	}
}