Decompiled source of LightBat v1.0.2

LightBat.dll

Decompiled 5 hours ago
#define DEBUG
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using LethalConfig;
using LethalConfig.ConfigItems;
using LethalConfig.ConfigItems.Options;
using LethalLib.Modules;
using LightBat.NetcodePatcher;
using Microsoft.CodeAnalysis;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.AI;
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: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("LightBat")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.5.14.0")]
[assembly: AssemblyInformationalVersion("1.5.14+3fa48b0ac7566ae8d1afb254877f0e76fda72420")]
[assembly: AssemblyProduct("LightBat")]
[assembly: AssemblyTitle("LightBat")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.5.14.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
[module: NetcodePatchedAssembly]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace LightBat
{
	internal static class DepletedApparatusRegistry
	{
		private static readonly int EmissiveColorProperty = Shader.PropertyToID("_EmissiveColor");

		private static readonly int EmissiveColorLdrProperty = Shader.PropertyToID("_EmissiveColorLDR");

		private static readonly int EmissiveIntensityProperty = Shader.PropertyToID("_EmissiveIntensity");

		private static readonly int StandardEmissionColorProperty = Shader.PropertyToID("_EmissionColor");

		private static readonly Dictionary<ulong, DepletedApparatusState> ActiveStates = new Dictionary<ulong, DepletedApparatusState>();

		private static GameObject? StatePrefab { get; set; }

		internal static bool Register(AssetBundle assets)
		{
			if ((Object)(object)StatePrefab != (Object)null)
			{
				return true;
			}
			GameObject val = assets.LoadAsset<GameObject>("DepletedApparatusState");
			if ((Object)(object)val == (Object)null || (Object)(object)val.GetComponent<NetworkObject>() == (Object)null || (Object)(object)val.GetComponent<DepletedApparatusState>() == (Object)null)
			{
				Plugin.Logger.LogError((object)"The asset bundle is missing the depleted Apparatus network state prefab.");
				return false;
			}
			NetworkPrefabs.RegisterNetworkPrefab(val);
			StatePrefab = val;
			Plugin.Logger.LogInfo((object)"Registered the persistent depleted Apparatus network state.");
			return true;
		}

		internal static bool SpawnState(LungProp apparatus, int scrapValue)
		{
			//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_0107: Unknown result type (might be due to invalid IL or missing references)
			NetworkObject val = default(NetworkObject);
			if ((Object)(object)apparatus == (Object)null || (Object)(object)StatePrefab == (Object)null || (Object)(object)NetworkManager.Singleton == (Object)null || !NetworkManager.Singleton.IsServer || !((Component)apparatus).TryGetComponent<NetworkObject>(ref val) || !val.IsSpawned)
			{
				return false;
			}
			ulong networkObjectId = val.NetworkObjectId;
			if (ActiveStates.TryGetValue(networkObjectId, out DepletedApparatusState value) && (Object)(object)value != (Object)null && ((NetworkBehaviour)value).IsSpawned)
			{
				ApplyState(apparatus, scrapValue);
				return true;
			}
			ActiveStates.Remove(networkObjectId);
			GameObject val2 = Object.Instantiate<GameObject>(StatePrefab, Vector3.zero, Quaternion.identity);
			NetworkObject component = val2.GetComponent<NetworkObject>();
			DepletedApparatusState component2 = val2.GetComponent<DepletedApparatusState>();
			if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null)
			{
				Object.Destroy((Object)(object)val2);
				return false;
			}
			component.Spawn(false);
			ActiveStates[networkObjectId] = component2;
			component2.Initialize(new NetworkObjectReference(val), scrapValue);
			return true;
		}

		internal static void UnregisterState(DepletedApparatusState state)
		{
			ulong? num = null;
			foreach (KeyValuePair<ulong, DepletedApparatusState> activeState in ActiveStates)
			{
				if ((Object)(object)activeState.Value == (Object)(object)state)
				{
					num = activeState.Key;
					break;
				}
			}
			if (num.HasValue)
			{
				ActiveStates.Remove(num.Value);
			}
		}

		internal static void ApplyState(LungProp apparatus, int scrapValue)
		{
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Expected O, but got Unknown
			//IL_013c: 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_015e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)apparatus == (Object)null)
			{
				return;
			}
			apparatus.isLungPowered = false;
			((GrabbableObject)apparatus).isBeingUsed = false;
			apparatus.lungDeviceLightIntensity = 0f;
			((GrabbableObject)apparatus).SetScrapValue(Mathf.Max(0, scrapValue));
			Light[] componentsInChildren = ((Component)apparatus).GetComponentsInChildren<Light>(true);
			foreach (Light val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null))
				{
					val.intensity = 0f;
					((Behaviour)val).enabled = false;
				}
			}
			ParticleSystem[] componentsInChildren2 = ((Component)apparatus).GetComponentsInChildren<ParticleSystem>(true);
			foreach (ParticleSystem val2 in componentsInChildren2)
			{
				if (!((Object)(object)val2 == (Object)null))
				{
					val2.Stop(true, (ParticleSystemStopBehavior)0);
				}
			}
			if ((Object)(object)apparatus.sparkParticle != (Object)null)
			{
				apparatus.sparkParticle.SetActive(false);
			}
			MaterialPropertyBlock val3 = new MaterialPropertyBlock();
			Renderer[] componentsInChildren3 = ((Component)apparatus).GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val4 in componentsInChildren3)
			{
				if (!((Object)(object)val4 == (Object)null) && !((Object)((Component)val4).transform).name.StartsWith("ScanNode", StringComparison.OrdinalIgnoreCase))
				{
					val4.GetPropertyBlock(val3);
					val3.SetColor(EmissiveColorProperty, Color.black);
					val3.SetColor(EmissiveColorLdrProperty, Color.black);
					val3.SetColor(StandardEmissionColorProperty, Color.black);
					val3.SetFloat(EmissiveIntensityProperty, 0f);
					val4.SetPropertyBlock(val3);
					val3.Clear();
				}
			}
		}
	}
	public sealed class DepletedApparatusState : NetworkBehaviour
	{
		private const float ResolveTimeout = 15f;

		private const float MissingTargetDespawnDelay = 5f;

		private const float StateEnforcementInterval = 0.75f;

		private readonly NetworkVariable<NetworkObjectReference> targetApparatus = new NetworkVariable<NetworkObjectReference>(default(NetworkObjectReference), (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0);

		private readonly NetworkVariable<bool> initialized = new NetworkVariable<bool>(false, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0);

		internal readonly NetworkVariable<int> finalScrapValue = new NetworkVariable<int>(30, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0);

		private Coroutine? resolveCoroutine;

		private float missingTargetTime;

		private float nextStateEnforcementTime;

		internal void Initialize(NetworkObjectReference apparatusReference, int finalScrapValue)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			if (!((NetworkBehaviour)this).IsServer || !((NetworkBehaviour)this).IsSpawned)
			{
				Plugin.Logger.LogError((object)"Tried to initialize a depleted Apparatus state before its network object was spawned.");
				return;
			}
			targetApparatus.Value = apparatusReference;
			this.finalScrapValue.Value = finalScrapValue;
			initialized.Value = true;
			StartResolvingTarget();
		}

		public override void OnNetworkSpawn()
		{
			((NetworkBehaviour)this).OnNetworkSpawn();
			NetworkVariable<NetworkObjectReference> obj = targetApparatus;
			obj.OnValueChanged = (OnValueChangedDelegate<NetworkObjectReference>)(object)Delegate.Combine((Delegate?)(object)obj.OnValueChanged, (Delegate?)(object)new OnValueChangedDelegate<NetworkObjectReference>(OnTargetChanged));
			NetworkVariable<bool> obj2 = initialized;
			obj2.OnValueChanged = (OnValueChangedDelegate<bool>)(object)Delegate.Combine((Delegate?)(object)obj2.OnValueChanged, (Delegate?)(object)new OnValueChangedDelegate<bool>(OnInitializedChanged));
			if (initialized.Value)
			{
				StartResolvingTarget();
			}
		}

		public override void OnNetworkDespawn()
		{
			DepletedApparatusRegistry.UnregisterState(this);
			NetworkVariable<NetworkObjectReference> obj = targetApparatus;
			obj.OnValueChanged = (OnValueChangedDelegate<NetworkObjectReference>)(object)Delegate.Remove((Delegate?)(object)obj.OnValueChanged, (Delegate?)(object)new OnValueChangedDelegate<NetworkObjectReference>(OnTargetChanged));
			NetworkVariable<bool> obj2 = initialized;
			obj2.OnValueChanged = (OnValueChangedDelegate<bool>)(object)Delegate.Remove((Delegate?)(object)obj2.OnValueChanged, (Delegate?)(object)new OnValueChangedDelegate<bool>(OnInitializedChanged));
			if (resolveCoroutine != null)
			{
				((MonoBehaviour)this).StopCoroutine(resolveCoroutine);
				resolveCoroutine = null;
			}
			((NetworkBehaviour)this).OnNetworkDespawn();
		}

		private void Update()
		{
			//IL_002a: 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)
			if (!((NetworkBehaviour)this).IsSpawned || !initialized.Value)
			{
				return;
			}
			NetworkObjectReference value = targetApparatus.Value;
			NetworkObject val = default(NetworkObject);
			LungProp apparatus = default(LungProp);
			if (((NetworkObjectReference)(ref value)).TryGet(ref val, (NetworkManager)null) && ((Component)val).TryGetComponent<LungProp>(ref apparatus))
			{
				missingTargetTime = 0f;
				if (Time.time >= nextStateEnforcementTime)
				{
					DepletedApparatusRegistry.ApplyState(apparatus, finalScrapValue.Value);
					nextStateEnforcementTime = Time.time + 0.75f;
				}
			}
			else if (((NetworkBehaviour)this).IsServer)
			{
				missingTargetTime += Time.deltaTime;
				if (missingTargetTime >= 5f)
				{
					((NetworkBehaviour)this).NetworkObject.Despawn(true);
				}
			}
		}

		private void OnTargetChanged(NetworkObjectReference previous, NetworkObjectReference current)
		{
			if (initialized.Value)
			{
				StartResolvingTarget();
			}
		}

		private void OnInitializedChanged(bool previous, bool current)
		{
			if (current)
			{
				StartResolvingTarget();
			}
		}

		private void StartResolvingTarget()
		{
			if (((NetworkBehaviour)this).IsSpawned && !TryApplyState())
			{
				if (resolveCoroutine != null)
				{
					((MonoBehaviour)this).StopCoroutine(resolveCoroutine);
				}
				resolveCoroutine = ((MonoBehaviour)this).StartCoroutine(ResolveTarget());
			}
		}

		private IEnumerator ResolveTarget()
		{
			float startedAt = Time.realtimeSinceStartup;
			while (((NetworkBehaviour)this).IsSpawned && initialized.Value && Time.realtimeSinceStartup - startedAt < 15f)
			{
				if (TryApplyState())
				{
					resolveCoroutine = null;
					yield break;
				}
				yield return null;
			}
			resolveCoroutine = null;
			if (((NetworkBehaviour)this).IsSpawned && initialized.Value)
			{
				Plugin.Logger.LogWarning((object)"Could not resolve the Apparatus for a replicated depleted Apparatus state.");
			}
		}

		private bool TryApplyState()
		{
			//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)
			if (initialized.Value)
			{
				NetworkObjectReference value = targetApparatus.Value;
				NetworkObject val = default(NetworkObject);
				LungProp apparatus = default(LungProp);
				if (((NetworkObjectReference)(ref value)).TryGet(ref val, (NetworkManager)null) && ((Component)val).TryGetComponent<LungProp>(ref apparatus))
				{
					DepletedApparatusRegistry.ApplyState(apparatus, finalScrapValue.Value);
					nextStateEnforcementTime = Time.time + 0.75f;
					return true;
				}
			}
			return false;
		}

		protected override void __initializeVariables()
		{
			if (targetApparatus == null)
			{
				throw new Exception("DepletedApparatusState.targetApparatus cannot be null. All NetworkVariableBase instances must be initialized.");
			}
			((NetworkVariableBase)targetApparatus).Initialize((NetworkBehaviour)(object)this);
			((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)targetApparatus, "targetApparatus");
			base.NetworkVariableFields.Add((NetworkVariableBase)(object)targetApparatus);
			if (initialized == null)
			{
				throw new Exception("DepletedApparatusState.initialized cannot be null. All NetworkVariableBase instances must be initialized.");
			}
			((NetworkVariableBase)initialized).Initialize((NetworkBehaviour)(object)this);
			((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)initialized, "initialized");
			base.NetworkVariableFields.Add((NetworkVariableBase)(object)initialized);
			if (finalScrapValue == null)
			{
				throw new Exception("DepletedApparatusState.finalScrapValue cannot be null. All NetworkVariableBase instances must be initialized.");
			}
			((NetworkVariableBase)finalScrapValue).Initialize((NetworkBehaviour)(object)this);
			((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)finalScrapValue, "finalScrapValue");
			base.NetworkVariableFields.Add((NetworkVariableBase)(object)finalScrapValue);
			((NetworkBehaviour)this).__initializeVariables();
		}

		protected override void __initializeRpcs()
		{
			((NetworkBehaviour)this).__initializeRpcs();
		}

		protected internal override string __getTypeName()
		{
			return "DepletedApparatusState";
		}
	}
	internal static class DischargedLampRegistry
	{
		private static readonly int EmissiveColorProperty = Shader.PropertyToID("_EmissiveColor");

		private static readonly int EmissiveColorLdrProperty = Shader.PropertyToID("_EmissiveColorLDR");

		private static readonly int EmissiveIntensityProperty = Shader.PropertyToID("_EmissiveIntensity");

		private static readonly int StandardEmissionColorProperty = Shader.PropertyToID("_EmissionColor");

		internal static Item? Item { get; private set; }

		private static GameObject? StatePrefab { get; set; }

		internal static bool Register(AssetBundle assets)
		{
			if ((Object)(object)Item != (Object)null)
			{
				return true;
			}
			Item val = assets.LoadAsset<Item>("DischargedLamp");
			GameObject val2 = assets.LoadAsset<GameObject>("DischargedLampState");
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Logger.LogError((object)"The asset bundle is missing the Discharged lamp Item.");
				return false;
			}
			if ((Object)(object)val2 == (Object)null || (Object)(object)val2.GetComponent<NetworkObject>() == (Object)null || (Object)(object)val2.GetComponent<DischargedLampState>() == (Object)null)
			{
				Plugin.Logger.LogError((object)"The asset bundle is missing the Discharged lamp network state prefab.");
				return false;
			}
			GameObject spawnPrefab = val.spawnPrefab;
			PhysicsProp val3 = (((Object)(object)spawnPrefab != (Object)null) ? spawnPrefab.GetComponent<PhysicsProp>() : null);
			if ((Object)(object)spawnPrefab == (Object)null || (Object)(object)spawnPrefab.GetComponent<NetworkObject>() == (Object)null || (Object)(object)val3 == (Object)null)
			{
				Plugin.Logger.LogError((object)"The Discharged lamp Item has an invalid network prefab.");
				return false;
			}
			((Object)val).name = "DischargedLamp";
			val.itemName = "Discharged lamp";
			((GrabbableObject)val3).itemProperties = val;
			NetworkPrefabs.RegisterNetworkPrefab(spawnPrefab);
			NetworkPrefabs.RegisterNetworkPrefab(val2);
			Items.RegisterItem(val);
			Item = val;
			StatePrefab = val2;
			Plugin.Logger.LogInfo((object)"Registered Discharged lamp as a non-spawning LethalLib item.");
			return true;
		}

		internal static bool SpawnState(GrabbableObject lamp, int scrapValue)
		{
			//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_00a5: Unknown result type (might be due to invalid IL or missing references)
			NetworkObject val = default(NetworkObject);
			if ((Object)(object)lamp == (Object)null || (Object)(object)StatePrefab == (Object)null || (Object)(object)NetworkManager.Singleton == (Object)null || !NetworkManager.Singleton.IsServer || !((Component)lamp).TryGetComponent<NetworkObject>(ref val) || !val.IsSpawned)
			{
				return false;
			}
			GameObject val2 = Object.Instantiate<GameObject>(StatePrefab, Vector3.zero, Quaternion.identity);
			NetworkObject component = val2.GetComponent<NetworkObject>();
			DischargedLampState component2 = val2.GetComponent<DischargedLampState>();
			if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null)
			{
				Object.Destroy((Object)(object)val2);
				return false;
			}
			component.Spawn(false);
			component2.Initialize(new NetworkObjectReference(val), scrapValue);
			return true;
		}

		internal static void ApplyState(GrabbableObject lamp, int scrapValue)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Expected O, but got Unknown
			//IL_00d7: 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_00f9: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)lamp == (Object)null)
			{
				return;
			}
			lamp.insertedBattery = new Battery(true, 0f);
			lamp.isBeingUsed = false;
			lamp.itemUsedUp = false;
			Light[] componentsInChildren = ((Component)lamp).GetComponentsInChildren<Light>(true);
			foreach (Light val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null))
				{
					val.intensity = 0f;
					((Behaviour)val).enabled = false;
				}
			}
			MaterialPropertyBlock val2 = new MaterialPropertyBlock();
			Renderer[] componentsInChildren2 = ((Component)lamp).GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val3 in componentsInChildren2)
			{
				if (!((Object)(object)val3 == (Object)null) && !((Object)((Component)val3).transform).name.StartsWith("ScanNode", StringComparison.OrdinalIgnoreCase))
				{
					val3.GetPropertyBlock(val2);
					val2.SetColor(EmissiveColorProperty, Color.black);
					val2.SetColor(EmissiveColorLdrProperty, Color.black);
					val2.SetColor(StandardEmissionColorProperty, Color.black);
					val2.SetFloat(EmissiveIntensityProperty, 0f);
					val3.SetPropertyBlock(val2);
					val2.Clear();
				}
			}
			if ((Object)(object)Item != (Object)null)
			{
				lamp.itemProperties = Item;
			}
			lamp.SetScrapValue(Mathf.Max(0, scrapValue));
			ScanNodeProperties componentInChildren = ((Component)lamp).GetComponentInChildren<ScanNodeProperties>(true);
			if ((Object)(object)componentInChildren != (Object)null)
			{
				componentInChildren.headerText = "Discharged lamp";
			}
			RefreshLocalInventoryIcon(lamp);
		}

		private static void RefreshLocalInventoryIcon(GrabbableObject lamp)
		{
			if ((Object)(object)Item == (Object)null || (Object)(object)Item.itemIcon == (Object)null || (Object)(object)GameNetworkManager.Instance == (Object)null || (Object)(object)HUDManager.Instance == (Object)null)
			{
				return;
			}
			PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController;
			if ((Object)(object)localPlayerController == (Object)null || localPlayerController.ItemSlots == null)
			{
				return;
			}
			for (int i = 0; i < localPlayerController.ItemSlots.Length; i++)
			{
				if (!((Object)(object)localPlayerController.ItemSlots[i] != (Object)(object)lamp))
				{
					if (typeof(HUDManager).GetField("itemSlotIcons")?.GetValue(HUDManager.Instance) is Array array && i < array.Length)
					{
						object value = array.GetValue(i);
						value?.GetType().GetProperty("sprite")?.SetValue(value, Item.itemIcon);
					}
					break;
				}
			}
		}
	}
	public sealed class DischargedLampState : NetworkBehaviour
	{
		private const float ResolveTimeout = 15f;

		private const float MissingTargetDespawnDelay = 5f;

		private readonly NetworkVariable<NetworkObjectReference> targetLamp = new NetworkVariable<NetworkObjectReference>(default(NetworkObjectReference), (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0);

		private readonly NetworkVariable<int> dischargedValue = new NetworkVariable<int>(0, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0);

		private readonly NetworkVariable<bool> initialized = new NetworkVariable<bool>(false, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0);

		private Coroutine? resolveCoroutine;

		private float missingTargetTime;

		internal void Initialize(NetworkObjectReference lampReference, int scrapValue)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			if (!((NetworkBehaviour)this).IsServer || !((NetworkBehaviour)this).IsSpawned)
			{
				Plugin.Logger.LogError((object)"Tried to initialize a Discharged lamp state before its network object was spawned.");
				return;
			}
			targetLamp.Value = lampReference;
			dischargedValue.Value = Mathf.Max(0, scrapValue);
			initialized.Value = true;
			StartResolvingTarget();
		}

		public override void OnNetworkSpawn()
		{
			((NetworkBehaviour)this).OnNetworkSpawn();
			NetworkVariable<NetworkObjectReference> obj = targetLamp;
			obj.OnValueChanged = (OnValueChangedDelegate<NetworkObjectReference>)(object)Delegate.Combine((Delegate?)(object)obj.OnValueChanged, (Delegate?)(object)new OnValueChangedDelegate<NetworkObjectReference>(OnTargetChanged));
			NetworkVariable<int> obj2 = dischargedValue;
			obj2.OnValueChanged = (OnValueChangedDelegate<int>)(object)Delegate.Combine((Delegate?)(object)obj2.OnValueChanged, (Delegate?)(object)new OnValueChangedDelegate<int>(OnValueChanged));
			NetworkVariable<bool> obj3 = initialized;
			obj3.OnValueChanged = (OnValueChangedDelegate<bool>)(object)Delegate.Combine((Delegate?)(object)obj3.OnValueChanged, (Delegate?)(object)new OnValueChangedDelegate<bool>(OnInitializedChanged));
			if (initialized.Value)
			{
				StartResolvingTarget();
			}
		}

		public override void OnNetworkDespawn()
		{
			NetworkVariable<NetworkObjectReference> obj = targetLamp;
			obj.OnValueChanged = (OnValueChangedDelegate<NetworkObjectReference>)(object)Delegate.Remove((Delegate?)(object)obj.OnValueChanged, (Delegate?)(object)new OnValueChangedDelegate<NetworkObjectReference>(OnTargetChanged));
			NetworkVariable<int> obj2 = dischargedValue;
			obj2.OnValueChanged = (OnValueChangedDelegate<int>)(object)Delegate.Remove((Delegate?)(object)obj2.OnValueChanged, (Delegate?)(object)new OnValueChangedDelegate<int>(OnValueChanged));
			NetworkVariable<bool> obj3 = initialized;
			obj3.OnValueChanged = (OnValueChangedDelegate<bool>)(object)Delegate.Remove((Delegate?)(object)obj3.OnValueChanged, (Delegate?)(object)new OnValueChangedDelegate<bool>(OnInitializedChanged));
			if (resolveCoroutine != null)
			{
				((MonoBehaviour)this).StopCoroutine(resolveCoroutine);
				resolveCoroutine = null;
			}
			((NetworkBehaviour)this).OnNetworkDespawn();
		}

		private void Update()
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			if (!((NetworkBehaviour)this).IsServer || !((NetworkBehaviour)this).IsSpawned || !initialized.Value)
			{
				return;
			}
			NetworkObjectReference value = targetLamp.Value;
			NetworkObject val = default(NetworkObject);
			if (((NetworkObjectReference)(ref value)).TryGet(ref val, (NetworkManager)null))
			{
				missingTargetTime = 0f;
				return;
			}
			missingTargetTime += Time.deltaTime;
			if (missingTargetTime >= 5f)
			{
				((NetworkBehaviour)this).NetworkObject.Despawn(true);
			}
		}

		private void OnTargetChanged(NetworkObjectReference previous, NetworkObjectReference current)
		{
			if (initialized.Value)
			{
				StartResolvingTarget();
			}
		}

		private void OnValueChanged(int previous, int current)
		{
			if (initialized.Value)
			{
				StartResolvingTarget();
			}
		}

		private void OnInitializedChanged(bool previous, bool current)
		{
			if (current)
			{
				StartResolvingTarget();
			}
		}

		private void StartResolvingTarget()
		{
			if (((NetworkBehaviour)this).IsSpawned && !TryApplyState())
			{
				if (resolveCoroutine != null)
				{
					((MonoBehaviour)this).StopCoroutine(resolveCoroutine);
				}
				resolveCoroutine = ((MonoBehaviour)this).StartCoroutine(ResolveTarget());
			}
		}

		private IEnumerator ResolveTarget()
		{
			float startedAt = Time.realtimeSinceStartup;
			while (((NetworkBehaviour)this).IsSpawned && initialized.Value && Time.realtimeSinceStartup - startedAt < 15f)
			{
				if (TryApplyState())
				{
					resolveCoroutine = null;
					yield break;
				}
				yield return null;
			}
			resolveCoroutine = null;
			if (((NetworkBehaviour)this).IsSpawned && initialized.Value)
			{
				Plugin.Logger.LogWarning((object)"Could not resolve the Fancy lamp for a replicated Discharged lamp state.");
			}
		}

		private bool TryApplyState()
		{
			//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)
			if (initialized.Value)
			{
				NetworkObjectReference value = targetLamp.Value;
				NetworkObject val = default(NetworkObject);
				GrabbableObject lamp = default(GrabbableObject);
				if (((NetworkObjectReference)(ref value)).TryGet(ref val, (NetworkManager)null) && ((Component)val).TryGetComponent<GrabbableObject>(ref lamp))
				{
					DischargedLampRegistry.ApplyState(lamp, dischargedValue.Value);
					return true;
				}
			}
			return false;
		}

		protected override void __initializeVariables()
		{
			if (targetLamp == null)
			{
				throw new Exception("DischargedLampState.targetLamp cannot be null. All NetworkVariableBase instances must be initialized.");
			}
			((NetworkVariableBase)targetLamp).Initialize((NetworkBehaviour)(object)this);
			((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)targetLamp, "targetLamp");
			base.NetworkVariableFields.Add((NetworkVariableBase)(object)targetLamp);
			if (dischargedValue == null)
			{
				throw new Exception("DischargedLampState.dischargedValue cannot be null. All NetworkVariableBase instances must be initialized.");
			}
			((NetworkVariableBase)dischargedValue).Initialize((NetworkBehaviour)(object)this);
			((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)dischargedValue, "dischargedValue");
			base.NetworkVariableFields.Add((NetworkVariableBase)(object)dischargedValue);
			if (initialized == null)
			{
				throw new Exception("DischargedLampState.initialized cannot be null. All NetworkVariableBase instances must be initialized.");
			}
			((NetworkVariableBase)initialized).Initialize((NetworkBehaviour)(object)this);
			((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)initialized, "initialized");
			base.NetworkVariableFields.Add((NetworkVariableBase)(object)initialized);
			((NetworkBehaviour)this).__initializeVariables();
		}

		protected override void __initializeRpcs()
		{
			((NetworkBehaviour)this).__initializeRpcs();
		}

		protected internal override string __getTypeName()
		{
			return "DischargedLampState";
		}
	}
	internal static class UtilityFlashlightInventory
	{
		internal const int UtilitySlotIndex = 50;

		private static readonly MethodInfo? SwitchToItemSlotMethod = AccessTools.Method(typeof(PlayerControllerB), "SwitchToItemSlot", new Type[2]
		{
			typeof(int),
			typeof(GrabbableObject)
		}, (Type[])null);

		private static readonly MethodInfo? SwitchToSlotServerRpcMethod = AccessTools.Method(typeof(PlayerControllerB), "SwitchToSlotServerRpc", new Type[1] { typeof(int) }, (Type[])null);

		private static readonly FieldInfo? ThrowingObjectField = AccessTools.Field(typeof(PlayerControllerB), "throwingObject");

		internal static bool IsInUtilitySlot(PlayerControllerB player, FlashlightItem flashlight)
		{
			return (Object)(object)player != (Object)null && (Object)(object)flashlight != (Object)null && (Object)(object)player.ItemOnlySlot == (Object)(object)flashlight;
		}

		internal static int FindNormalSlot(PlayerControllerB player, FlashlightItem flashlight)
		{
			if (player.ItemSlots == null)
			{
				return -1;
			}
			for (int i = 0; i < player.ItemSlots.Length; i++)
			{
				if ((Object)(object)player.ItemSlots[i] == (Object)(object)flashlight)
				{
					return i;
				}
			}
			return -1;
		}

		internal static bool IsStoredByPlayer(PlayerControllerB player, FlashlightItem flashlight)
		{
			return IsInUtilitySlot(player, flashlight) || FindNormalSlot(player, flashlight) >= 0 || (Object)(object)player.pocketedFlashlight == (Object)(object)flashlight || (Object)(object)player.currentlyHeldObjectServer == (Object)(object)flashlight || (Object)(object)player.currentlyHeldObject == (Object)(object)flashlight;
		}

		internal static int FindStoredSlot(PlayerControllerB player, FlashlightItem flashlight)
		{
			if (IsInUtilitySlot(player, flashlight))
			{
				return 50;
			}
			return FindNormalSlot(player, flashlight);
		}

		internal static bool IsInActiveHand(PlayerControllerB player, FlashlightItem flashlight)
		{
			if ((Object)(object)player == (Object)null || (Object)(object)flashlight == (Object)null || ((GrabbableObject)flashlight).isPocketed)
			{
				return false;
			}
			if (!((player.currentItemSlot != 50) ? (player.ItemSlots != null && player.currentItemSlot >= 0 && player.currentItemSlot < player.ItemSlots.Length && (Object)(object)player.ItemSlots[player.currentItemSlot] == (Object)(object)flashlight) : ((Object)(object)player.ItemOnlySlot == (Object)(object)flashlight)))
			{
				return false;
			}
			return !((NetworkBehaviour)player).IsOwner || (Object)(object)player.currentlyHeldObjectServer == (Object)(object)flashlight || (Object)(object)player.currentlyHeldObject == (Object)(object)flashlight;
		}

		internal static bool SwitchToStoredFlashlight(PlayerControllerB player, FlashlightItem flashlight)
		{
			int num = FindStoredSlot(player, flashlight);
			if (SwitchToItemSlotMethod == null || SwitchToSlotServerRpcMethod == null || num < 0 || (num != 50 && (player.ItemSlots == null || num >= player.ItemSlots.Length)))
			{
				return false;
			}
			GrabbableObject currentlyHeldObjectServer = player.currentlyHeldObjectServer;
			FlashlightItem val = (FlashlightItem)(((object)((currentlyHeldObjectServer is FlashlightItem) ? currentlyHeldObjectServer : null)) ?? ((object)/*isinst with value type is only supported in some contexts*/));
			if ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)flashlight && LightBatAI.IsFlashlightInteractionLocked(val))
			{
				return false;
			}
			try
			{
				SwitchToItemSlotMethod.Invoke(player, new object[2] { num, null });
				if (!IsInActiveHand(player, flashlight))
				{
					return false;
				}
				SwitchToSlotServerRpcMethod.Invoke(player, new object[1] { num });
				return true;
			}
			catch (Exception arg)
			{
				Plugin.Logger.LogError((object)$"Could not deploy a stored flashlight into hand: {arg}");
				return false;
			}
		}

		internal static bool IsThrowingObject(PlayerControllerB player)
		{
			object obj = ThrowingObjectField?.GetValue(player);
			return obj is bool && (bool)obj;
		}
	}
	[HarmonyPatch(typeof(FlashlightItem), "ItemActivate")]
	internal static class LockedFlashlightActivationPatch
	{
		[HarmonyPrefix]
		private static bool AllowActivation(FlashlightItem __instance)
		{
			return !LightBatAI.IsFlashlightInteractionLocked(__instance);
		}
	}
	[HarmonyPatch(typeof(FlashlightItem), "PocketItem")]
	internal static class LockedFlashlightPocketPatch
	{
		[HarmonyPrefix]
		private static bool AllowPocketing(FlashlightItem __instance)
		{
			return !LightBatAI.IsFlashlightInteractionLocked(__instance);
		}
	}
	[HarmonyPatch(typeof(FlashlightItem), "Update")]
	internal static class LockedFlashlightUpdatePatch
	{
		[HarmonyPostfix]
		private static void KeepAttachedFlashlightOn(FlashlightItem __instance)
		{
			if (LightBatAI.IsFlashlightInteractionLocked(__instance) && ((GrabbableObject)__instance).insertedBattery != null && !((GrabbableObject)__instance).insertedBattery.empty && !(((GrabbableObject)__instance).insertedBattery.charge <= 0f))
			{
				((GrabbableObject)__instance).isBeingUsed = true;
				if ((Object)(object)__instance.flashlightBulb != (Object)null && !((Behaviour)__instance.flashlightBulb).enabled)
				{
					__instance.SwitchFlashlight(true);
				}
			}
		}
	}
	[HarmonyPatch(typeof(PlayerControllerB), "SwitchToItemSlot")]
	internal static class LockedFlashlightInventorySlotPatch
	{
		[HarmonyPrefix]
		private static bool AllowSlotSwitch(PlayerControllerB __instance, int slot)
		{
			if (slot == __instance.currentItemSlot)
			{
				return true;
			}
			GrabbableObject currentlyHeldObjectServer = __instance.currentlyHeldObjectServer;
			FlashlightItem val = (FlashlightItem)(((object)((currentlyHeldObjectServer is FlashlightItem) ? currentlyHeldObjectServer : null)) ?? ((object)/*isinst with value type is only supported in some contexts*/));
			return (Object)(object)val == (Object)null || !LightBatAI.IsFlashlightInteractionLocked(val);
		}
	}
	[HarmonyPatch(typeof(PlayerControllerB), "DiscardHeldObject")]
	internal static class LockedFlashlightDiscardPatch
	{
		[HarmonyPrefix]
		internal static bool AllowDiscard(PlayerControllerB __instance)
		{
			if (__instance.isPlayerDead)
			{
				return true;
			}
			GrabbableObject currentlyHeldObjectServer = __instance.currentlyHeldObjectServer;
			FlashlightItem val = (FlashlightItem)(((object)((currentlyHeldObjectServer is FlashlightItem) ? currentlyHeldObjectServer : null)) ?? ((object)/*isinst with value type is only supported in some contexts*/));
			return (Object)(object)val == (Object)null || !LightBatAI.IsFlashlightInteractionLocked(val);
		}
	}
	[HarmonyPatch(typeof(PlayerControllerB), "Discard_performed")]
	internal static class LockedFlashlightDiscardInputPatch
	{
		[HarmonyPrefix]
		private static bool AllowDiscardInput(PlayerControllerB __instance)
		{
			return LockedFlashlightDiscardPatch.AllowDiscard(__instance);
		}
	}
	public sealed class LightBatAI : EnemyAI
	{
		private enum ApparatusPhase
		{
			None,
			Approaching,
			Perched,
			Hauling,
			Draining
		}

		private sealed class ApparatusFlock
		{
			public ulong ApparatusId;

			public LungProp Apparatus = null;

			public int Generation;

			public readonly List<LightBatAI> Members = new List<LightBatAI>();

			public ApparatusPhase Phase = ApparatusPhase.Approaching;

			public bool Ending;

			public int SimulatedFrame = -1;

			public PlayerControllerB? Holder;

			public GameObject NavObject = null;

			public NavMeshAgent Nav = null;

			public bool NavReady;

			public Vector3 HaulOrigin;

			public Vector3 HaulDestination;

			public bool HasHaulDestination;

			public float HaulStartedAt;

			public float HaulProgressAt;

			public Vector3 HaulProgressPosition;

			public float NextHaulReplanAt;

			public int HaulReplanCount;

			public float HaulHeight;

			public Vector3 CarryPosition;

			public Vector3 CarryFacing;

			public float CarryYaw;

			public int CarryTick;

			public float NextCarryPublishAt;

			public float PullStartedAt = -1f;

			public Vector3 PullDirection;

			public Vector3 PullDestination;

			public bool HasPullDestination;

			public float NextPullDestinationAt;

			public Vector3 PublishedPull;

			public bool DrainActive;

			public bool DrainCompleted;

			public float DrainElapsed;

			public float NextDrainSyncAt;

			public float PhaseEnteredAt;

			public float PerchedSince = -1f;

			public float UnperchedSince = -1f;

			public int PublishedPerchedCount = -1;
		}

		private sealed class ApparatusHold
		{
			public ulong ApparatusId;

			public LungProp Apparatus = null;

			public int Generation;

			public GameObject AnchorObject = null;

			public Transform Anchor = null;

			public Vector3 SmoothPosition;

			public float SmoothYaw;

			public bool Primed;

			public int AppliedTick = int.MinValue;

			public int AppliedFrame = -1;

			public int TouchedFrame = -1;
		}

		private sealed class ApparatusLightVisualState
		{
			public LungProp Apparatus = null;

			public Light[] Lights = null;

			public float[] FullIntensities = null;
		}

		private sealed class ApparatusLiftState
		{
			public float Height;

			public float GroundY;

			public bool HasGround;

			public bool HoldingVertical;

			public int TouchedFrame = -1;
		}

		private sealed class ApparatusDrainProgress
		{
			public float Elapsed;

			public int StartValue;

			public int TargetValue;

			public bool Completed;
		}

		private sealed class ApparatusHoldDriver : MonoBehaviour
		{
			private void LateUpdate()
			{
				SweepOrphanedApparatusHolds();
			}
		}

		private sealed class ApparatusShape
		{
			public LungProp Apparatus = null;

			public Vector3 LocalCenter;

			public Vector3 Extents;
		}

		private sealed class BurnMeshState
		{
			public SkinnedMeshRenderer BodyRenderer = null;

			public SkinnedMeshRenderer EdgeRenderer = null;

			public Mesh OriginalMesh = null;

			public Mesh BodyMesh = null;

			public Mesh EdgeMesh = null;

			public int[][] SourceTriangles = null;

			public float[][] TriangleScores = null;

			public List<int>[] BodyTriangles = null;

			public List<int>[] EdgeTriangles = null;
		}

		private sealed class SharedFacilityLightState
		{
			public Animator Animator = null;

			public Light[] Lights = null;

			public float[] FullIntensities = null;

			public float RemainingEnergy = 1f;

			public float FlickerStartedAt;

			public float FlickerEndsAt;

			public readonly Dictionary<ulong, int> PerchSlots = new Dictionary<ulong, int>();
		}

		private sealed class FlashlightRaid
		{
			public ulong FlashlightId;

			public FlashlightItem Flashlight = null;

			public PlayerControllerB Player = null;

			public LightBatAI Volunteer = null;

			public readonly List<LightBatAI> Members = new List<LightBatAI>();

			public bool Ending;

			public int RaidGeneration;

			public bool DeployingFlashlight;

			public bool OwnerConfirmedEquipped;

			public int DeploymentRequestId;

			public float DeploymentStartedAt;

			public float NextDeploymentRequestAt;

			public float HandStableSince = -1f;

			public float ReturnCooldown = 8f;
		}

		private sealed class LampVisualState
		{
			public Light[] Lights = null;

			public float[] FullIntensities = null;
		}

		private sealed class LampValueState
		{
			public GrabbableObject Lamp = null;

			public int OriginalScrapValue;
		}

		private enum State
		{
			SearchingForLight,
			FlyingToLight,
			Perching,
			Draining,
			Fleeing,
			FlyingToRaidFlashlight,
			AttachedToFlashlight,
			OrbitingFlashlightPlayer,
			FlyingToHeldApparatus,
			PerchedOnHeldApparatus,
			CarryingApparatus,
			FlyingToDroppedApparatus,
			DrainingApparatus
		}

		private enum TargetKind
		{
			None,
			FacilityLight,
			Flashlight,
			ItemLamp
		}

		private const float ApparatusAttachDistance = 0.85f;

		private const float ApparatusApproachRepathInterval = 0.55f;

		private const float ApparatusApproachStallTime = 0.7f;

		private const float ApparatusApproachGiveUpTime = 7f;

		private const float ApparatusFlockAbandonTime = 20f;

		private const int ApparatusHoldSweepFrames = 12;

		private const float ApparatusMaximumPull = 4f;

		private const float ApparatusMaximumAirbornePull = 5.5f;

		private const float ApparatusLiftRiseRate = 1.1f;

		private const float ApparatusLiftFallRate = 2.6f;

		private const float ApparatusLiftStiffness = 6f;

		private const float ApparatusLiftMaximumVerticalSpeed = 4f;

		private const float ApparatusLiftPlayerHeight = 2.6f;

		private const float ApparatusLiftCeilingMargin = 0.3f;

		private const float ApparatusLiftMinimumHeight = 0.2f;

		private const float ApparatusLiftProbeAhead = 1.6f;

		private const float ApparatusLiftProbeCeiling = 8f;

		private const float ApparatusLiftGroundProbe = 12f;

		private const float ApparatusLiftGroundTrackRate = 3f;

		private const int ApparatusLiftExpiryFrames = 8;

		private const float ApparatusHaulStallTime = 0.7f;

		private const float ApparatusHaulReplanCooldown = 0.45f;

		private const float ApparatusHaulTimeout = 26f;

		private const float ApparatusHaulArriveDistance = 2.2f;

		private const float ApparatusHaulMinimumDisplacement = 7f;

		private const float ApparatusPerchSettleTime = 0.45f;

		private const float ApparatusReturnCooldown = 6f;

		private const float ApparatusDepletedCooldown = 14f;

		private const float ApparatusPullRampTime = 1.2f;

		private const float ApparatusPullDestinationInterval = 6f;

		private const float ApparatusCarryPublishInterval = 0.05f;

		private const float ApparatusDrainSyncInterval = 0.15f;

		private const float ApparatusDoorOpenCooldown = 1.1f;

		private const float ApparatusDoorScanDistance = 3.6f;

		private const int ApparatusSlotsPerRing = 5;

		private const int ApparatusFinalScrapMinimum = 30;

		private const int ApparatusFinalScrapMaximumExclusive = 46;

		private readonly NetworkVariable<NetworkObjectReference> syncedApparatus = new NetworkVariable<NetworkObjectReference>(default(NetworkObjectReference), (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)1);

		private readonly NetworkVariable<int> syncedApparatusPhase = new NetworkVariable<int>(0, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)1);

		private readonly NetworkVariable<int> syncedApparatusSlot = new NetworkVariable<int>(-1, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)1);

		private readonly NetworkVariable<int> syncedApparatusGeneration = new NetworkVariable<int>(0, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)1);

		private readonly NetworkVariable<int> syncedApparatusPerchedCount = new NetworkVariable<int>(0, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)1);

		private readonly NetworkVariable<Vector3> syncedApparatusPull = new NetworkVariable<Vector3>(Vector3.zero, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)1);

		private readonly NetworkVariable<Vector3> syncedApparatusCarryPosition = new NetworkVariable<Vector3>(Vector3.zero, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)1);

		private readonly NetworkVariable<float> syncedApparatusCarryYaw = new NetworkVariable<float>(0f, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)1);

		private readonly NetworkVariable<int> syncedApparatusCarryTick = new NetworkVariable<int>(0, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)1);

		private static readonly Dictionary<ulong, ApparatusFlock> activeApparatusFlocks = new Dictionary<ulong, ApparatusFlock>();

		private static readonly Dictionary<ulong, ApparatusHold> apparatusHolds = new Dictionary<ulong, ApparatusHold>();

		private static readonly Dictionary<int, ApparatusLightVisualState> apparatusLightVisualStates = new Dictionary<int, ApparatusLightVisualState>();

		private static readonly Dictionary<int, float> nextApparatusDoorOpenTime = new Dictionary<int, float>();

		private static readonly Dictionary<ulong, int> apparatusPullFrame = new Dictionary<ulong, int>();

		private static readonly Dictionary<ulong, ApparatusDrainProgress> apparatusDrainProgress = new Dictionary<ulong, ApparatusDrainProgress>();

		private static readonly Dictionary<ulong, ApparatusLiftState> apparatusLiftStates = new Dictionary<ulong, ApparatusLiftState>();

		private static readonly List<ulong> apparatusLiftSweepBuffer = new List<ulong>();

		private static readonly HashSet<ulong> announcedApparatusDrains = new HashSet<ulong>();

		private static readonly List<ulong> apparatusHoldSweepBuffer = new List<ulong>();

		private static StartOfRound? apparatusSessionRound;

		private static int apparatusSessionSeed = int.MinValue;

		private static int apparatusSessionLevelId = int.MinValue;

		private static int apparatusHoldSweepFrame = -1;

		private static int nextApparatusFlockGeneration;

		private ApparatusFlock? activeApparatusFlock;

		private LungProp? cachedApparatus;

		private int apparatusSlot = -1;

		private bool apparatusActuallyPerched;

		private float nextApparatusFlockAllowedTime;

		private Vector3 apparatusApproachProgressPosition;

		private float apparatusApproachProgressAt;

		private float apparatusApproachStartedAt;

		private float nextApparatusApproachRepathAt;

		private Vector3 apparatusApproachDetour;

		private bool apparatusGroundPoseApplied;

		private static ApparatusHoldDriver? apparatusHoldDriver;

		private static readonly Dictionary<int, ApparatusShape> apparatusShapes = new Dictionary<int, ApparatusShape>();

		[Header("LightBat")]
		public Transform visualRoot = null;

		public AudioClip[] flapSounds = null;

		public AudioClip burningSound = null;

		public Material burnEdgeMaterial = null;

		private const float PerchDistance = 1.1f;

		private const float MovingTargetBreakDistance = 2.2f;

		private const float FacilityPerchOffset = 0.25f;

		private const float DroppedFlashlightPerchOffset = 0.65f;

		private const float ItemLampPerchOffset = 0.28f;

		private const int CarriedLightTier = 0;

		private const int FacilityLightTier = 1;

		private const float DischargedLampValueMultiplier = 0.4f;

		private const float MinimumFlightHeight = 0.65f;

		private const float NavMeshProjectionRadius = 3f;

		private const float MaximumTargetNavOffset = 1.15f;

		private const float FinalObstacleReleaseDistance = 1.35f;

		private const float ModelHalfHeight = 0.62f;

		private const float ModelCollisionRadius = 0.48f;

		private const float FacilityTargetStuckTime = 4f;

		private const float FailedFacilityTargetCooldown = 600f;

		private const float CruiseHeightVariation = 0.72f;

		private const float HeightLaneStep = 0.618034f;

		private const float ClearanceLookAheadDistance = 3.8f;

		private const float ClearanceProbeSpacing = 0.55f;

		private const float ClearanceProbeRadius = 0.2f;

		private const float FinalPathProbeRadius = 0.16f;

		private const float FinalTargetAllowance = 0.28f;

		private const float HitFearLevel = 0.7f;

		private const float FleeSafeDistance = 16f;

		private const float FleeMinimumTime = 1.5f;

		private const float FleeMaximumTime = 10f;

		private const float FleeRepathInterval = 0.75f;

		private const float FleeSpeedMultiplier = 1.85f;

		private const float LandingFlickerDuration = 0.7f;

		private const float SharedLampPerchRadius = 0.28f;

		private const float AdditionalPerchRingSpacing = 0.42f;

		private const int PerchSlotsPerRing = 12;

		private const float ActiveAgentRadius = 0.5f;

		private const float PerchedAgentRadius = 0.05f;

		private const float RaidAttachDistance = 0.62f;

		private const float RaidFlashlightForwardOffset = 0.16f;

		private const float RaidFlashlightVerticalOffset = 0.22f;

		private const float RaidOrbitRadius = 3.1f;

		private const float RaidOrbitRingSpacing = 0.42f;

		private const int RaidOrbitSlotsPerRing = 8;

		private const float RaidOrbitDegreesPerSecond = 38f;

		private const float RaidReturnCooldown = 8f;

		private const float RaidStressLevel = 0.24f;

		private const float RaidStressInterval = 0.65f;

		private const float FlashlightDeploymentRetryInterval = 0.65f;

		private const float FlashlightDeploymentTimeout = 7f;

		private const float FlashlightHandSettleTime = 0.3f;

		private const float FlashlightDeploymentFailureCooldown = 1.25f;

		private const float FlapSoundVolume = 0.55f;

		private const float MinimumFlapPitch = 1.25f;

		private const float MaximumFlapPitch = 1.4f;

		private const float EnergizedDuration = 10f;

		private const float EnergizedSpeedMultiplier = 1.65f;

		private const float EnergizedAnimationSpeed = 1.25f;

		private const float SunlightBurnDuration = 3.8f;

		private const float SunlightBurnSoundVolume = 0.85f;

		private const float SunlightBurnEdgeWidth = 0.055f;

		private const int SunlightBurnIgnitionPointCount = 7;

		private const float MinimumVisualBoundsExtent = 2.5f;

		private const int EyeGlowMaterialIndex = 1;

		private static readonly int EmissiveColorProperty = Shader.PropertyToID("_EmissiveColor");

		private static readonly int EmissiveColorLdrProperty = Shader.PropertyToID("_EmissiveColorLDR");

		private static readonly int EmissiveIntensityProperty = Shader.PropertyToID("_EmissiveIntensity");

		private static readonly int StandardEmissionColorProperty = Shader.PropertyToID("_EmissionColor");

		private static readonly Color EyeEnergyColor = new Color(1f, 0.5f, 0.14f, 1f);

		private static readonly int[] PerchSlotOrder = new int[12]
		{
			0, 6, 3, 9, 1, 7, 4, 10, 2, 8,
			5, 11
		};

		private readonly NetworkVariable<bool> syncedFinalClimb = new NetworkVariable<bool>(false, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)1);

		private readonly NetworkVariable<float> syncedCruiseHeightOffset = new NetworkVariable<float>(0f, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)1);

		private readonly NetworkVariable<NetworkObjectReference> syncedRaidFlashlight = new NetworkVariable<NetworkObjectReference>(default(NetworkObjectReference), (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)1);

		private readonly NetworkVariable<NetworkObjectReference> syncedBurnFlashlight = new NetworkVariable<NetworkObjectReference>(default(NetworkObjectReference), (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)1);

		private readonly NetworkVariable<NetworkObjectReference> syncedBurnLamp = new NetworkVariable<NetworkObjectReference>(default(NetworkObjectReference), (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)1);

		private readonly NetworkVariable<NetworkObjectReference> syncedBurnApparatus = new NetworkVariable<NetworkObjectReference>(default(NetworkObjectReference), (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)1);

		private readonly NetworkVariable<int> syncedBurnApparatusSlot = new NetworkVariable<int>(-1, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)1);

		private readonly NetworkVariable<bool> syncedEnergized = new NetworkVariable<bool>(false, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)1);

		private readonly NetworkVariable<bool> syncedBurningOut = new NetworkVariable<bool>(false, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)1);

		private readonly NetworkVariable<float> syncedDissolveProgress = new NetworkVariable<float>(0f, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)1);

		private readonly AISearchRoutine wideSearch = new AISearchRoutine
		{
			loopSearch = true,
			searchWidth = 200f,
			searchPrecision = 12f,
			randomized = true
		};

		private readonly Dictionary<int, float> blockedFacilityTargets = new Dictionary<int, float>();

		private TargetKind targetKind;

		private int targetFacilityLightIndex = -1;

		private FlashlightItem? targetFlashlight;

		private GrabbableObject? targetLamp;

		private PlayerControllerB? fleeFromPlayer;

		private Vector3 fleeDestination;

		private float nextFleeRepathTime;

		private float stateTimer;

		private float retargetCooldown;

		private Vector3 visualRootStartPosition;

		private Vector3 targetNavigationPosition;

		private float targetPathDistance;

		private float bestTargetPathDistance;

		private float timeAtLastTargetProgress;

		private float smoothedVerticalSpeed;

		private float smoothedYaw;

		private float yawVelocity;

		private float previousRootYaw;

		private float smoothedVisualTurnRate;

		private Vector3 previousRootPosition;

		private float smoothedRootSpeed;

		private Renderer? eyeGlowRenderer;

		private MaterialPropertyBlock? eyeGlowProperties;

		private float eyeGlowCharge;

		private static int heightLaneSequence;

		private float nextClearanceProbeTime;

		private float cachedSafeFlightHeight = float.PositiveInfinity;

		private Coroutine? facilityDrainCoroutine;

		private Coroutine? facilityFlickerCoroutine;

		private Coroutine? flashlightDrainCoroutine;

		private Coroutine? lampDrainCoroutine;

		private Coroutine? flashlightDeploymentCoroutine;

		private int nextFlashlightDeploymentRequestId;

		private int activeLocalFlashlightDeploymentGeneration;

		private int latestCancelledFlashlightRaidGeneration;

		private int localRaidAttachmentGeneration;

		private ulong activeLampDrainId;

		private bool hasActiveLampDrain;

		private float lastHitSoundTime = float.NegativeInfinity;

		private int reservedFacilityAnimatorId = -1;

		private ulong reservedPerchOwnerId;

		private int reservedPerchSlot = -1;

		private Vector3 reservedPerchOffset;

		private int reservedLampInstanceId = -1;

		private FlashlightRaid? activeFlashlightRaid;

		private bool isFlashlightRaidVolunteer;

		private FlashlightItem? cachedRaidFlashlight;

		private FlashlightItem? cachedBurnFlashlight;

		private LungProp? cachedBurnApparatus;

		private GrabbableObject? cachedBurnLamp;

		private int flashlightRaidOrbitSlot = -1;

		private float nextFlashlightRaidAllowedTime;

		private float nextRaidStressPulseTime;

		private bool attachedAnimationEnabled;

		private bool wingFlapTrackingActive;

		private float previousWingCycle;

		private int lastFlapSoundIndex = -1;

		private float energizedUntilTime;

		private float sunlightBurnStartedAt;

		private bool deathFallInitialized;

		private bool deathFallSettled;

		private float deathFallSpeed;

		private float deathGroundY;

		private float deathSettleTimer;

		private float deathPoseSink;

		private Mesh? deathPoseMesh;

		private SkinnedMeshRenderer? deathPoseRenderer;

		private const float DeathPoseSettleTime = 1.5f;

		private float burnPlaybackStartedAt;

		private float displayedDissolveProgress;

		private bool burnPlaybackInitialized;

		private bool burnMaterialApplied;

		private bool burningAudioStarted;

		private AudioSource? burningAudioSource;

		private readonly List<BurnMeshState> burnMeshes = new List<BurnMeshState>();

		private MaterialPropertyBlock? burnProperties;

		private static readonly Dictionary<int, SharedFacilityLightState> sharedFacilityLights = new Dictionary<int, SharedFacilityLightState>();

		private static readonly Dictionary<ulong, FlashlightRaid> activeFlashlightRaids = new Dictionary<ulong, FlashlightRaid>();

		private static readonly HashSet<int> lockedFlashlights = new HashSet<int>();

		private static readonly Dictionary<int, ulong> reservedItemLamps = new Dictionary<int, ulong>();

		private static readonly HashSet<ulong> activeLampDrains = new HashSet<ulong>();

		private static readonly Dictionary<int, LampVisualState> lampVisualStates = new Dictionary<int, LampVisualState>();

		private static readonly Dictionary<ulong, LampValueState> lampValueStates = new Dictionary<ulong, LampValueState>();

		private bool ApparatusPoseIsGrounded => apparatusGroundPoseApplied;

		private void ResetApparatusSupportLocally()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			EnsureApparatusSessionState();
			activeApparatusFlock = null;
			cachedApparatus = null;
			apparatusSlot = -1;
			apparatusActuallyPerched = false;
			apparatusApproachDetour = Vector3.zero;
			nextApparatusApproachRepathAt = 0f;
			ClearApparatusGroundDrainPose();
		}

		private static void EnsureApparatusSessionState()
		{
			StartOfRound instance = StartOfRound.Instance;
			if ((Object)(object)instance == (Object)null || (apparatusSessionRound == instance && apparatusSessionSeed == instance.randomMapSeed && apparatusSessionLevelId == instance.currentLevelID))
			{
				return;
			}
			apparatusSessionRound = instance;
			apparatusSessionSeed = instance.randomMapSeed;
			apparatusSessionLevelId = instance.currentLevelID;
			foreach (ApparatusFlock value in activeApparatusFlocks.Values)
			{
				DestroyApparatusNav(value);
			}
			foreach (ApparatusHold value2 in apparatusHolds.Values)
			{
				if ((Object)(object)value2.AnchorObject != (Object)null)
				{
					Object.Destroy((Object)(object)value2.AnchorObject);
				}
			}
			activeApparatusFlocks.Clear();
			apparatusHolds.Clear();
			apparatusLightVisualStates.Clear();
			apparatusShapes.Clear();
			nextApparatusDoorOpenTime.Clear();
			apparatusPullFrame.Clear();
			apparatusDrainProgress.Clear();
			apparatusLiftStates.Clear();
			announcedApparatusDrains.Clear();
			apparatusHoldSweepBuffer.Clear();
			apparatusLiftSweepBuffer.Clear();
			nextApparatusFlockGeneration = 0;
		}

		private void ResetSyncedApparatusState()
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: 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)
			if (((NetworkBehaviour)this).IsOwner && ((NetworkBehaviour)this).IsSpawned)
			{
				syncedApparatus.Value = default(NetworkObjectReference);
				syncedApparatusPhase.Value = 0;
				syncedApparatusSlot.Value = -1;
				syncedApparatusGeneration.Value = 0;
				syncedApparatusPerchedCount.Value = 0;
				syncedApparatusPull.Value = Vector3.zero;
				syncedApparatusCarryPosition.Value = Vector3.zero;
				syncedApparatusCarryYaw.Value = 0f;
				syncedApparatusCarryTick.Value = 0;
			}
		}

		private bool TryStartOrJoinApparatusFlock()
		{
			//IL_00bb: 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)
			EnsureApparatusSessionState();
			if (!((NetworkBehaviour)this).IsServer || activeApparatusFlock != null || activeFlashlightRaid != null || (Object)(object)StartOfRound.Instance == (Object)null || base.isEnemyDead || syncedBurningOut.Value || Time.time < nextApparatusFlockAllowedTime)
			{
				return false;
			}
			float num = Mathf.Max(5f, 30f);
			LungProp val = null;
			NetworkObject val2 = null;
			float num2 = num;
			LungProp[] array = Object.FindObjectsOfType<LungProp>();
			NetworkObject val4 = default(NetworkObject);
			foreach (LungProp val3 in array)
			{
				if (ApparatusIsAvailable(val3) && ((Component)val3).TryGetComponent<NetworkObject>(ref val4) && val4.IsSpawned)
				{
					float num3 = Vector3.Distance(((Component)this).transform.position, GetApparatusCenter(val3));
					if (!(num3 >= num2))
					{
						val = val3;
						val2 = val4;
						num2 = num3;
					}
				}
			}
			if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
			{
				return false;
			}
			ulong networkObjectId = val2.NetworkObjectId;
			if (activeApparatusFlocks.TryGetValue(networkObjectId, out ApparatusFlock value))
			{
				if (value.Ending || (Object)(object)value.Apparatus == (Object)null)
				{
					EndApparatusFlock(value, depleted: false);
					activeApparatusFlocks.Remove(networkObjectId);
					return false;
				}
				JoinApparatusFlock(value);
				return true;
			}
			ApparatusFlock apparatusFlock = new ApparatusFlock
			{
				ApparatusId = networkObjectId,
				Apparatus = val,
				Generation = ++nextApparatusFlockGeneration,
				Phase = ApparatusPhase.Approaching,
				PhaseEnteredAt = Time.time,
				Holder = (((GrabbableObject)val).isHeld ? ((GrabbableObject)val).playerHeldBy : null)
			};
			activeApparatusFlocks[networkObjectId] = apparatusFlock;
			LightBatAI[] array2 = Object.FindObjectsOfType<LightBatAI>();
			foreach (LightBatAI lightBatAI in array2)
			{
				if (lightBatAI.CanJoinApparatusFlock(val))
				{
					lightBatAI.JoinApparatusFlock(apparatusFlock);
				}
			}
			if (apparatusFlock.Members.Count == 0)
			{
				activeApparatusFlocks.Remove(networkObjectId);
				return false;
			}
			LogDebug($"LightBat Apparatus flock #{apparatusFlock.Generation} started with " + $"{apparatusFlock.Members.Count} bats.");
			return true;
		}

		private bool CanJoinApparatusFlock(LungProp apparatus)
		{
			//IL_006f: 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)
			if (!((NetworkBehaviour)this).IsOwner || !((NetworkBehaviour)this).IsServer || !((NetworkBehaviour)this).IsSpawned || base.isEnemyDead || syncedBurningOut.Value || activeApparatusFlock != null || activeFlashlightRaid != null || base.currentBehaviourStateIndex == 4 || Time.time < nextApparatusFlockAllowedTime || !ApparatusIsAvailable(apparatus))
			{
				return false;
			}
			return Vector3.Distance(((Component)this).transform.position, GetApparatusCenter(apparatus)) <= Mathf.Max(5f, 30f);
		}

		private static bool ApparatusIsAvailable(LungProp apparatus)
		{
			if ((Object)(object)apparatus == (Object)null || !((Component)apparatus).gameObject.activeInHierarchy || !apparatus.isLungPowered || ((GrabbableObject)apparatus).scrapValue <= 0 || ((GrabbableObject)apparatus).isPocketed || ((GrabbableObject)apparatus).deactivated)
			{
				return false;
			}
			if (ApparatusIsDocked(apparatus))
			{
				return false;
			}
			if (((GrabbableObject)apparatus).isHeld || (Object)(object)((GrabbableObject)apparatus).playerHeldBy != (Object)null)
			{
				PlayerControllerB playerHeldBy = ((GrabbableObject)apparatus).playerHeldBy;
				return (Object)(object)playerHeldBy != (Object)null && playerHeldBy.isPlayerControlled && !playerHeldBy.isPlayerDead && playerHeldBy.isInsideFactory && !playerHeldBy.isInHangarShipRoom;
			}
			return ((GrabbableObject)apparatus).isInFactory && !((GrabbableObject)apparatus).isInShipRoom && !((GrabbableObject)apparatus).isInElevator;
		}

		private static bool ApparatusIsPlayerHeld(LungProp apparatus)
		{
			return (Object)(object)apparatus != (Object)null && ((GrabbableObject)apparatus).isHeld && !((GrabbableObject)apparatus).isPocketed && (Object)(object)((GrabbableObject)apparatus).playerHeldBy != (Object)null;
		}

		private static bool ApparatusIsDocked(LungProp apparatus)
		{
			return (Object)(object)apparatus != (Object)null && (apparatus.isLungDocked || apparatus.isLungDockedInElevator);
		}

		private static bool ApparatusHasLeftFacility(LungProp apparatus)
		{
			if ((Object)(object)apparatus == (Object)null)
			{
				return false;
			}
			if (((GrabbableObject)apparatus).isHeld && (Object)(object)((GrabbableObject)apparatus).playerHeldBy != (Object)null)
			{
				return !((GrabbableObject)apparatus).playerHeldBy.isInsideFactory;
			}
			return !((GrabbableObject)apparatus).isInFactory || ((GrabbableObject)apparatus).isInShipRoom || ((GrabbableObject)apparatus).isInElevator;
		}

		private void JoinApparatusFlock(ApparatusFlock flock)
		{
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			if (base.currentSearch.inProgress)
			{
				((EnemyAI)this).StopSearch(base.currentSearch, true);
			}
			if (base.currentBehaviourStateIndex == 3)
			{
				CancelActiveDrainServerRpc();
			}
			ClearTarget();
			activeApparatusFlock = flock;
			cachedApparatus = flock.Apparatus;
			apparatusSlot = FindOpenApparatusSlot(flock);
			apparatusActuallyPerched = false;
			apparatusApproachProgressPosition = ((Component)this).transform.position;
			apparatusApproachProgressAt = Time.time;
			apparatusApproachStartedAt = Time.time;
			nextApparatusApproachRepathAt = 0f;
			apparatusApproachDetour = Vector3.zero;
			flock.Members.Add(this);
			flock.UnperchedSince = -1f;
			PublishApparatusState(flock, ApparatusPhase.Approaching);
			TransitionTo((flock.Phase == ApparatusPhase.Draining) ? State.FlyingToDroppedApparatus : State.FlyingToHeldApparatus);
		}

		private static int FindOpenApparatusSlot(ApparatusFlock flock)
		{
			int num = 0;
			bool flag;
			do
			{
				flag = false;
				foreach (LightBatAI member in flock.Members)
				{
					if ((Object)(object)member != (Object)null && member.apparatusSlot == num)
					{
						flag = true;
						num++;
						break;
					}
				}
			}
			while (flag);
			return num;
		}

		private void PublishApparatusState(ApparatusFlock flock, ApparatusPhase phase)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			NetworkObject val = default(NetworkObject);
			if (((NetworkBehaviour)this).IsOwner && ((NetworkBehaviour)this).IsSpawned && !((Object)(object)flock.Apparatus == (Object)null) && ((Component)flock.Apparatus).TryGetComponent<NetworkObject>(ref val) && val.IsSpawned)
			{
				syncedApparatus.Value = new NetworkObjectReference(val);
				syncedApparatusPhase.Value = (int)phase;
				syncedApparatusSlot.Value = apparatusSlot;
				syncedApparatusGeneration.Value = flock.Generation;
			}
		}

		private bool TryGetValidApparatusFlock(out ApparatusFlock flock)
		{
			flock = activeApparatusFlock;
			ApparatusFlock value;
			return flock != null && !flock.Ending && (Object)(object)flock.Apparatus != (Object)null && flock.Members.Contains(this) && activeApparatusFlocks.TryGetValue(flock.ApparatusId, out value) && value == flock;
		}

		private void UpdateApparatusFlockSimulation()
		{
			if (((NetworkBehaviour)this).IsServer && TryGetValidApparatusFlock(out ApparatusFlock flock) && flock.SimulatedFrame != Time.frameCount)
			{
				flock.SimulatedFrame = Time.frameCount;
				SimulateApparatusFlock(flock);
			}
		}

		private void SimulateApparatusFlock(ApparatusFlock flock)
		{
			LungProp apparatus = flock.Apparatus;
			if ((Object)(object)apparatus == (Object)null || ((GrabbableObject)apparatus).deactivated)
			{
				EndApparatusFlock(flock, depleted: false);
				return;
			}
			PruneApparatusFlockMembers(flock);
			if (flock.Members.Count == 0)
			{
				EndApparatusFlock(flock, depleted: false);
				return;
			}
			int num = CountPerchedApparatusBats(flock);
			PublishApparatusPerchedCount(flock, num);
			bool flag = ApparatusIsPlayerHeld(apparatus);
			flock.Holder = (flag ? ((GrabbableObject)apparatus).playerHeldBy : null);
			if (!ApparatusIsAvailable(apparatus))
			{
				bool burnMembers = apparatus.isLungPowered && !((GrabbableObject)apparatus).deactivated && ApparatusHasLeftFacility(apparatus);
				EndApparatusFlock(flock, depleted: false, burnMembers);
				return;
			}
			if (flag)
			{
				if (flock.Phase != ApparatusPhase.Perched)
				{
					ReleaseApparatusCustody(flock, dropToFloor: false);
					flock.DrainActive = false;
					SetApparatusPhase(flock, ApparatusPhase.Perched);
				}
				UpdateApparatusPull(flock, num);
				return;
			}
			ClearApparatusPull(flock);
			switch (flock.Phase)
			{
			case ApparatusPhase.Approaching:
			case ApparatusPhase.Perched:
				if (num <= 0)
				{
					flock.PerchedSince = -1f;
					if (flock.UnperchedSince < 0f)
					{
						flock.UnperchedSince = Time.time;
					}
					else if (Time.time - flock.UnperchedSince >= 20f)
					{
						EndApparatusFlock(flock, depleted: false);
					}
					break;
				}
				flock.UnperchedSince = -1f;
				if (flock.PerchedSince < 0f)
				{
					flock.PerchedSince = Time.time;
				}
				if (!(Time.time - flock.PerchedSince < 0.45f))
				{
					if (ApparatusIsDocked(apparatus))
					{
						SetApparatusPhase(flock, ApparatusPhase.Draining);
					}
					else
					{
						BeginApparatusHaul(flock);
					}
				}
				break;
			case ApparatusPhase.Hauling:
				UpdateApparatusHaul(flock, num);
				break;
			case ApparatusPhase.Draining:
				UpdateApparatusDrain(flock, num);
				break;
			}
		}

		private void PruneApparatusFlockMembers(ApparatusFlock flock)
		{
			for (int num = flock.Members.Count - 1; num >= 0; num--)
			{
				LightBatAI lightBatAI = flock.Members[num];
				if ((Object)(object)lightBatAI == (Object)null)
				{
					flock.Members.RemoveAt(num);
				}
				else if (((EnemyAI)lightBatAI).isEnemyDead || lightBatAI.syncedBurningOut.Value || lightBatAI.activeApparatusFlock != flock)
				{
					flock.Members.RemoveAt(num);
					if (lightBatAI.activeApparatusFlock == flock)
					{
						lightBatAI.DetachFromApparatusFlock(6f);
					}
				}
			}
		}

		private static int CountPerchedApparatusBats(ApparatusFlock flock)
		{
			int num = 0;
			foreach (LightBatAI member in flock.Members)
			{
				if ((Object)(object)member != (Object)null && !((EnemyAI)member).isEnemyDead && member.apparatusActuallyPerched)
				{
					num++;
				}
			}
			return num;
		}

		private static void PublishApparatusPerchedCount(ApparatusFlock flock, int perched)
		{
			flock.PublishedPerchedCount = perched;
			foreach (LightBatAI member in flock.Members)
			{
				if ((Object)(object)member != (Object)null && ((NetworkBehaviour)member).IsOwner && ((NetworkBehaviour)member).IsSpawned && member.syncedApparatusPerchedCount.Value != perched)
				{
					member.syncedApparatusPerchedCount.Value = perched;
				}
			}
		}

		private void SetApparatusPhase(ApparatusFlock flock, ApparatusPhase phase)
		{
			if (flock.Phase == phase)
			{
				return;
			}
			flock.Phase = phase;
			flock.PhaseEnteredAt = Time.time;
			flock.PerchedSince = -1f;
			if (1 == 0)
			{
			}
			State state = phase switch
			{
				ApparatusPhase.Hauling => State.CarryingApparatus, 
				ApparatusPhase.Draining => State.DrainingApparatus, 
				ApparatusPhase.Perched => State.PerchedOnHeldApparatus, 
				_ => State.FlyingToHeldApparatus, 
			};
			if (1 == 0)
			{
			}
			State state2 = state;
			foreach (LightBatAI member in flock.Members)
			{
				if (!((Object)(object)member == (Object)null) && !((EnemyAI)member).isEnemyDead)
				{
					if (!member.apparatusActuallyPerched)
					{
						member.PublishApparatusState(flock, ApparatusPhase.Approaching);
						continue;
					}
					member.PublishApparatusState(flock, phase);
					member.TransitionTo(state2);
				}
			}
			LogDebug($"LightBat Apparatus flock #{flock.Generation} -> {phase}.");
		}

		private void FlyToApparatus()
		{
			//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_0053: 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_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_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_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0237: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0265: 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_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			if (!TryGetValidApparatusFlock(out ApparatusFlock flock))
			{
				DetachFromApparatusFlock(6f);
				return;
			}
			LungProp apparatus = flock.Apparatus;
			if (!ApparatusIsAvailable(apparatus))
			{
				return;
			}
			Vector3 apparatusAttachmentPosition = GetApparatusAttachmentPosition(apparatus, apparatusSlot);
			float num = Vector3.Distance(((Component)this).transform.position, apparatusAttachmentPosition);
			if (num <= 0.85f)
			{
				AttachToApparatus(flock);
				return;
			}
			OpenApparatusDoorsAhead(((Component)this).transform.position, apparatusAttachmentPosition - ((Component)this).transform.position, 3.6f);
			if (Vector3.Distance(((Component)this).transform.position, apparatusApproachProgressPosition) >= 0.35f)
			{
				apparatusApproachProgressPosition = ((Component)this).transform.position;
				apparatusApproachProgressAt = Time.time;
				apparatusApproachDetour = Vector3.zero;
			}
			else if (Time.time - apparatusApproachProgressAt >= 0.7f)
			{
				apparatusApproachProgressAt = Time.time;
				apparatusApproachDetour = PickApparatusDetour(apparatusAttachmentPosition);
				nextApparatusApproachRepathAt = 0f;
				if ((Object)(object)base.agent != (Object)null && ((Behaviour)base.agent).enabled && base.agent.isOnNavMesh)
				{
					base.agent.ResetPath();
				}
				if (Time.time - apparatusApproachStartedAt >= 7f)
				{
					LeaveApparatusFlock(flock, 6f);
					return;
				}
			}
			Vector3 targetPosition = apparatusAttachmentPosition + apparatusApproachDetour;
			if (Time.time >= nextApparatusApproachRepathAt || targetNavigationPosition == Vector3.zero)
			{
				nextApparatusApproachRepathAt = Time.time + 0.55f;
				if (!TryGetReachableNavigationPosition(targetPosition, out targetNavigationPosition, out targetPathDistance) && !TryGetReachableNavigationPosition(apparatusAttachmentPosition, out targetNavigationPosition, out targetPathDistance))
				{
					targetNavigationPosition = apparatusAttachmentPosition;
					targetPathDistance = num;
				}
			}
			SyncVisualTargetHeight(apparatusAttachmentPosition);
			if ((Object)(object)base.agent != (Object)null)
			{
				base.agent.speed = 3.4f;
			}
			((EnemyAI)this).SetDestinationToPosition(targetNavigationPosition, false);
		}

		private Vector3 PickApparatusDetour(Vector3 attachPosition)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: 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_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: 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_0037: 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_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = attachPosition - ((Component)this).transform.position;
			val.y = 0f;
			if (((Vector3)(ref val)).sqrMagnitude < 0.01f)
			{
				return Vector3.zero;
			}
			Vector3 val2 = Vector3.Cross(Vector3.up, ((Vector3)(ref val)).normalized);
			float num = ((Random.value < 0.5f) ? (-1f) : 1f);
			return val2 * (num * Random.Range(1.6f, 3.2f));
		}

		private void AttachToApparatus(ApparatusFlock flock)
		{
			//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)
			StopMoving();
			PrepareForFlashlightAttachment();
			apparatusActuallyPerched = true;
			apparatusApproachDetour = Vector3.zero;
			ApparatusPhase apparatusPhase = ((flock.Phase == ApparatusPhase.Approaching) ? ApparatusPhase.Perched : flock.Phase);
			PublishApparatusState(flock, apparatusPhase);
			if (1 == 0)
			{
			}
			State state = apparatusPhase switch
			{
				ApparatusPhase.Hauling => State.CarryingApparatus, 
				ApparatusPhase.Draining => State.DrainingApparatus, 
				_ => State.PerchedOnHeldApparatus, 
			};
			if (1 == 0)
			{
			}
			TransitionTo(state);
			LockToApparatus(flock.Apparatus, apparatusSlot);
		}

		private void UpdateApparatusPull(ApparatusFlock flock, int perched)
		{
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: 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_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: 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: Expected O, but got Unknown
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Invalid comparison between Unknown and I4
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: Unknown result type (might be due to invalid IL or missing references)
			//IL_0263: Unknown result type (might be due to invalid IL or missing references)
			//IL_0237: 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_0253: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: Unknown result type (might be due to invalid IL or missing references)
			//IL_025c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0264: Unknown result type (might be due to invalid IL or missing references)
			//IL_026a: Unknown result type (might be due to invalid IL or missing references)
			//IL_026b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0275: Unknown result type (might be due to invalid IL or missing references)
			//IL_027a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0280: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d7: Unknown result type (might be due to invalid IL or missing references)
			if (perched <= 0 || (Object)(object)flock.Holder == (Object)null)
			{
				ClearApparatusPull(flock);
				return;
			}
			if (flock.PullStartedAt < 0f)
			{
				flock.PullStartedAt = Time.time;
				flock.PullDirection = Vector3.zero;
				flock.HasPullDestination = false;
				flock.NextPullDestinationAt = 0f;
			}
			PlayerControllerB holder = flock.Holder;
			Vector3 position = ((Component)holder).transform.position;
			EnsureApparatusNav(flock, position);
			if (!flock.HasPullDestination || Time.time >= flock.NextPullDestinationAt || HorizontalDistance(position, flock.PullDestination) < 6f)
			{
				flock.NextPullDestinationAt = Time.time + 6f;
				Vector3 pullDestination = flock.PullDestination;
				bool hasPullDestination = flock.HasPullDestination;
				flock.HasPullDestination = TryChooseApparatusDestination(flock, position, 14f, 80f, pullDestination, hasPullDestination, out flock.PullDestination);
			}
			Vector3 val = Vector3.zero;
			if (flock.HasPullDestination && flock.NavReady && flock.Nav.isOnNavMesh)
			{
				NavMeshAgent nav = flock.Nav;
				NavMeshHit val2 = default(NavMeshHit);
				if (NavMesh.SamplePosition(position, ref val2, 3f, nav.areaMask))
				{
					nav.Warp(((NavMeshHit)(ref val2)).position);
				}
				NavMeshPath val3 = new NavMeshPath();
				if (nav.CalculatePath(flock.PullDestination, val3) && (int)val3.status != 2)
				{
					val = GetFirstMeaningfulPathDirection(val3, position, 1.4f);
				}
			}
			if (((Vector3)(ref val)).sqrMagnitude < 0.01f && flock.HasPullDestination)
			{
				val = flock.PullDestination - position;
				val.y = 0f;
			}
			if (((Vector3)(ref val)).sqrMagnitude < 0.01f)
			{
				val = -((Component)holder).transform.forward;
				val.y = 0f;
			}
			if (((Vector3)(ref val)).sqrMagnitude < 0.01f)
			{
				val = Vector3.forward;
			}
			((Vector3)(ref val)).Normalize();
			Vector3 pullDirection;
			if (!(((Vector3)(ref flock.PullDirection)).sqrMagnitude < 0.01f))
			{
				Vector3 val4 = Vector3.Slerp(flock.PullDirection, val, 1f - Mathf.Exp(-6f * Time.deltaTime));
				pullDirection = ((Vector3)(ref val4)).normalized;
			}
			else
			{
				pullDirection = val;
			}
			flock.PullDirection = pullDirection;
			OpenApparatusDoorsAhead(position + Vector3.up * 0.6f, flock.PullDirection, 3.6f);
			float num = Mathf.Clamp01((Time.time - flock.PullStartedAt) / 1.2f);
			num = num * num * (3f - 2f * num);
			float num2 = Mathf.Min(GetApparatusPullMagnitude(perched) * num, 4f);
			PublishApparatusPull(flock, flock.PullDirection * num2);
		}

		private static float GetApparatusPullMagnitude(int perched)
		{
			if (1 == 0)
			{
			}
			float result = ((perched <= 0) ? 0f : (perched switch
			{
				1 => 0.7f, 
				2 => 1.2f, 
				3 => 1.9f, 
				4 => 2.5f, 
				_ => 3.1f, 
			}));
			if (1 == 0)
			{
			}
			return result;
		}

		private static void ClearApparatusPull(ApparatusFlock flock)
		{
			//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_001f: Unknown result type (might be due to invalid IL or missing references)
			flock.PullStartedAt = -1f;
			flock.PullDirection = Vector3.zero;
			flock.HasPullDestination = false;
			PublishApparatusPull(flock, Vector3.zero);
		}

		private static void PublishApparatusPull(ApparatusFlock flock, Vector3 pull)
		{
			//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_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_0021: 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_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_008b: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = flock.PublishedPull - pull;
			bool flag = ((Vector3)(ref val)).sqrMagnitude >= 0.0004f;
			flock.PublishedPull = pull;
			foreach (LightBatAI member in flock.Members)
			{
				if (!((Object)(object)member == (Object)null) && ((NetworkBehaviour)member).IsOwner && ((NetworkBehaviour)member).IsSpawned && (flag || !(member.syncedApparatusPull.Value == pull)))
				{
					member.syncedApparatusPull.Value = pull;
				}
			}
		}

		private void UpdateApparatusPlayerPull()
		{
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: 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)
			if (base.isEnemyDead || syncedApparatusPhase.Value != 2 || syncedApparatusPerchedCount.Value <= 0 || (Object)(object)GameNetworkManager.Instance == (Object)null)
			{
				return;
			}
			PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController;
			NetworkObject val = default(NetworkObject);
			if ((Object)(object)localPlayerController == (Object)null || localPlayerController.isPlayerDead || localPlayerController.inSpecialInteractAnimation || localPlayerController.isClimbingLadder || !TryGetSyncedApparatus(out LungProp apparatus) || !ApparatusIsPlayerHeld(apparatus) || (Object)(object)((GrabbableObject)apparatus).playerHeldBy != (Object)(object)localPlayerController || !((Component)apparatus).TryGetComponent<NetworkObject>(ref val))
			{
				return;
			}
			ulong networkObjectId = val.NetworkObjectId;
			int frameCount = Time.frameCount;
			if (!apparatusPullFrame.TryGetValue(networkObjectId, out var value) || value != frameCount)
			{
				apparatusPullFrame[networkObjectId] = frameCount;
				Vector3 val2 = syncedApparatusPull.Value;
				val2.y = 0f;
				bool airborne;
				float num = UpdateApparatusLift(localPlayerController, syncedApparatusPerchedCount.Value, val2, frameCount, out airborne);
				if (airborne)
				{
					val2 = Vector3.ClampMagnitude(val2 * 1.35f, 5.5f);
				}
				localPlayerController.externalForces += new Vector3(val2.x, num, val2.z);
			}
		}

		private static float UpdateApparatusLift(PlayerControllerB player, int perched, Vector3 pull, int frame, out bool airborne)
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: 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_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: Unknown result type (might be due to invalid IL or missing references)
			airborne = false;
			if (perched < 4 || player.isInHangarShipRoom || player.isClimbingLadder || player.inSpecialInteractAnimation || player.isPlayerDead)
			{
				ReleaseApparatusLift(player);
				return 0f;
			}
			ulong playerClientId = player.playerClientId;
			Vector3 position = ((Component)player).transform.position;
			bool flag = false;
			if (!apparatusLiftStates.TryGetValue(playerClientId, out ApparatusLiftState value))
			{
				value = new ApparatusLiftState();
				apparatusLiftStates[playerClientId] = value;
				flag = true;
				EnsureApparatusHoldDriver();
			}
			else if (frame - value.TouchedFrame > 1)
			{
				flag = true;
				value.HoldingVertical = false;
				value.HasGround = false;
			}
			value.TouchedFrame = frame;
			float groundY;
			bool flag2 = TryFindApparatusLiftGround(position, out groundY);
			if (flag2)
			{
				value.GroundY = (value.HasGround ? Mathf.MoveTowards(value.GroundY, groundY, 3f * Time.deltaTime) : groundY);
				value.HasGround = true;
			}
			if (flag)
			{
				value.Height = (value.HasGround ? Mathf.Clamp(position.y - value.GroundY, 0f, 1.15f) : 0f);
			}
			float num;
			if (!flag2)
			{
				num = 0f;
			}
			else
			{
				float num2 = MeasureApparatusLiftCeiling(player, position, ResolveApparatusLiftDirection(player, pull));
				num = Mathf.Min(1.15f, num2 - value.GroundY - 2.6f - 0.3f);
				if (num < 0.2f)
				{
					num = 0f;
				}
			}
			value.Height = Mathf.MoveTowards(value.Height, num, ((num > value.Height) ? 1.1f : 2.6f) * Time.deltaTime);
			if (value.Height <= 0.01f && num <= 0f)
			{
				if (value.HoldingVertical)
				{
					value.HoldingVertical = false;
					NeutralizePlayerFall(player);
				}
				return 0f;
			}
			value.HoldingVertical = true;
			airborne = true;
			NeutralizePlayerFall(player);
			if (!value.HasGround)
			{
				return 0f;
			}
			float num3 = position.y - value.GroundY;
			return Mathf.Clamp((value.Height - num3) * 6f, -4f, 4f);
		}

		private static Vector3 ResolveApparatusLiftDirection(PlayerControllerB player, Vector3 pull)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			//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_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_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_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = pull;
			val.y = 0f;
			if (((Vector3)(ref val)).sqrMagnitude > 0.0001f)
			{
				((Vector3)(ref val)).Normalize();
			}
			else
			{
				val = Vector3.zero;
			}
			if ((Object)(object)player.thisController != (Object)null)
			{
				Vector3 velocity = player.thisController.velocity;
				velocity.y = 0f;
				if (((Vector3)(ref velocity)).sqrMagnitude > 0.04f)
				{
					val += ((Vector3)(ref velocity)).normalized * 1.5f;
				}
			}
			if (((Vector3)(ref val)).sqrMagnitude > 0.0001f)
			{
				return ((Vector3)(ref val)).normalized;
			}
			Vector3 forward = ((Component)player).transform.forward;
			forward.y = 0f;
			return (((Vector3)(ref forward)).sqrMagnitude > 0.0001f) ? ((Vector3)(ref forward)).normalized : Vector3.forward;
		}

		private static void ReleaseApparatusLift(PlayerControllerB player)
		{
			if (apparatusLiftStates.TryGetValue(player.playerClientId, out ApparatusLiftState value))
			{
				apparatusLiftStates.Remove(player.playerClientId);
				if (value.HoldingVertical)
				{
					NeutralizePlayerFall(player);
				}
			}
		}

		private static void NeutralizePlayerFall(PlayerControllerB player)
		{
			player.fallValue = 0f;
			player.fallValueUncapped = 0f;
			player.takingFallDamage = false;
		}

		private static bool TryFindApparatusLiftGround(Vector3 foot, out float groundY)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//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_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: 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_0093: Unknown result type (might be due to invalid IL or missing references)
			int num = (((Object)(object)StartOfRound.Instance != (Object)null) ? StartOfRound.Instance.collidersAndRoomMaskAndDefault : (-1));
			groundY = foot.y;
			RaycastHit[] array = Physics.RaycastAll(foot + Vector3.up * 0.3f, Vector3.down, 12f, num, (QueryTriggerInteraction)1);
			bool flag = false;
			float num2 = float.NegativeInfinity;
			RaycastHit[] array2 = array;
			for (int i = 0; i < array2.Length; i++)
			{
				RaycastHit hit = array2[i];
				if (ApparatusLiftProbeHitIsWorld(hit) && ((RaycastHit)(ref hit)).point.y > num2)
				{
					num2 = ((RaycastHit)(ref hit)).point.y;
					flag = true;
				}
			}
			if (flag)
			{
				groundY = num2;
			}
			return flag;
		}

		private static float MeasureApparatusLiftCeiling(PlayerControllerB player, Vector3 foot, Vector3 direction)
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00b4: 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_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: 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)
			int num = (((Object)(object)StartOfRound.Instance != (Object)null) ? StartOfRound.Instance.collidersAndRoomMaskAndDefault : (-1));
			float num2 = (((Object)(object)player.thisController != (Object)null) ? Mathf.Clamp(player.thisController.radius, 0.2f, 0.8f) : 0.5f);
			float num3 = foot.y + num2 + 0.1f;
			float num4 = 1.6f;
			RaycastHit val = default(RaycastHit);
			if (Physics.Raycast(new Vector3(foot.x, num3, foot.z), direction, ref val, 1.6f, num, (QueryTriggerInteraction)1))
			{
				num4 = Mathf.Max(0f, ((RaycastHit)(ref val)).distance - 0.15f);
			}
			float num5 = num3 + 8f;
			for (int i = 0; i <= 2; i++)
			{
				Vector3 val2 = foot + direction * (num4 * (float)i * 0.5f) + Vector3.up * (num2 + 0.1f);
				RaycastHit[] array = Physics.SphereCastAll(val2, num2, Vector3.up, 8f, num, (QueryTriggerInteraction)1);
				RaycastHit[] array2 = array;
				for (int j = 0; j < array2.Length; j++)
				{
					RaycastHit hit = array2[j];
					if (ApparatusLiftProbeHitIsWorld(hit))
					{
						num5 = Mathf.Min(num5, val2.y + ((RaycastHit)(ref hit)).distance + num2);
					}
				}
			}
			return num5;
		}

		private static bool ApparatusLiftProbeHitIsWorld(RaycastHit hit)
		{
			return (Object)(object)((RaycastHit)(ref hit)).collider != (Object)null && (Object)(object)((Component)((RaycastHit)(ref hit)).collider).GetComponentInParent<GrabbableObject>() == (Object)null && (Object)(object)((Component)((RaycastHit)(ref hit)).collider).GetComponentInParent<PlayerControllerB>() == (Object)null;
		}

		private static void ExpireApparatusLiftStates()
		{
			if (apparatusLiftStates.Count == 0)
			{
				return;
			}
			apparatusLiftSweepBuffer.Clear();
			foreach (KeyValuePair<ulong, ApparatusLiftState> apparatusLiftState in apparatusLiftStates)
			{
				if (Time.frameCount - apparatusLiftState.Value.TouchedFrame > 8)
				{
					apparatusLiftSweepBuffer.Add(apparatusLiftState.Key);
				}
			}
			foreach (ulong item in apparatusLiftSweepBuffer)