Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of LightBat v1.0.8
LightBat.dll
Decompiled a month ago
The result has been truncated due to the large size, download it to view full contents!
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.Events; using UnityEngine.Rendering; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("LightBat")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.5.14.0")] [assembly: AssemblyInformationalVersion("1.5.14+32232b3d8fbc21fec22ae47f05d6c6ce11c65438")] [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_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: 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_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Expected O, but got Unknown //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0124: 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_0026: 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_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) 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_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) 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"); private static readonly Vector3 SpawnedLampMeshCorrection = new Vector3(180f, 0f, 0f); private static Quaternion? authoredModelRotation; 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_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0089: 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_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown //IL_00b1: 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_00d1: 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); } internal static void CorrectSpawnedLampMesh() { //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_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_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) GameObject val = (((Object)(object)Item != (Object)null) ? Item.spawnPrefab : null); Transform val2 = (((Object)(object)val != (Object)null) ? val.transform.Find("Model") : null); if (!((Object)(object)val2 == (Object)null)) { Quaternion valueOrDefault = authoredModelRotation.GetValueOrDefault(); if (!authoredModelRotation.HasValue) { valueOrDefault = val2.localRotation; authoredModelRotation = valueOrDefault; } val2.localRotation = authoredModelRotation.Value * Quaternion.Euler(SpawnedLampMeshCorrection); } } 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; } } } } [HarmonyPatch(typeof(StartOfRound), "Start")] internal static class SpawnedLampMeshPatch { [HarmonyPostfix] private static void CorrectSpawnedLampMesh() { DischargedLampRegistry.CorrectSpawnedLampMesh(); } } 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_0026: 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_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) if (!((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_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) 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"); private static readonly FieldInfo? GrabbedObjectValidatedField = AccessTools.Field(typeof(PlayerControllerB), "grabbedObjectValidated"); private static readonly FieldInfo? GrabInvalidatedField = AccessTools.Field(typeof(PlayerControllerB), "grabInvalidated"); internal static bool IsInUtilitySlot(PlayerControllerB player, FlashlightItem flashlight) { if ((Object)(object)player != (Object)null && (Object)(object)flashlight != (Object)null) { return (Object)(object)player.ItemOnlySlot == (Object)(object)flashlight; } return false; } 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) { if (!IsInUtilitySlot(player, flashlight) && FindNormalSlot(player, flashlight) < 0 && !((Object)(object)player.pocketedFlashlight == (Object)(object)flashlight) && !((Object)(object)player.currentlyHeldObjectServer == (Object)(object)flashlight)) { return (Object)(object)player.currentlyHeldObject == (Object)(object)flashlight; } return true; } 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; } if (((NetworkBehaviour)player).IsOwner && !((Object)(object)player.currentlyHeldObjectServer == (Object)(object)flashlight)) { return (Object)(object)player.currentlyHeldObject == (Object)(object)flashlight; } return true; } 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; } if (player.isGrabbingObjectAnimation || IsThrowingObject(player)) { 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); if (obj is bool) { return (bool)obj; } return false; } internal static bool IsWaitingForGrabbedObject(PlayerControllerB player) { object obj = GrabbedObjectValidatedField?.GetValue(player); if (obj is bool) { return !(bool)obj; } return false; } internal static void InvalidateGrab(PlayerControllerB player) { GrabInvalidatedField?.SetValue(player, true); } } [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) { if (!LightBatAI.IsFlashlightInteractionLocked(__instance)) { return true; } PlayerControllerB playerHeldBy = ((GrabbableObject)__instance).playerHeldBy; if ((Object)(object)playerHeldBy != (Object)null) { return !UtilityFlashlightInventory.IsInActiveHand(playerHeldBy, __instance); } return false; } } [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), "Update")] internal static class StalledGrabRecoveryPatch { private const float StalledGrabTimeout = 5f; private static float stallStartedAt = -1f; [HarmonyPostfix] private static void RecoverStalledGrab(PlayerControllerB __instance) { if (!((Object)(object)GameNetworkManager.Instance == (Object)null) && !((Object)(object)GameNetworkManager.Instance.localPlayerController != (Object)(object)__instance)) { if (!__instance.isGrabbingObjectAnimation || !UtilityFlashlightInventory.IsWaitingForGrabbedObject(__instance)) { stallStartedAt = -1f; } else if (stallStartedAt < 0f) { stallStartedAt = Time.time; } else if (!(Time.time - stallStartedAt < 5f)) { stallStartedAt = -1f; Plugin.Logger.LogWarning((object)($"A pickup has been stuck for {5f:0.#}s without " + "the item ever arriving. Cancelling it so the player is not left unable to interact.")); UtilityFlashlightInventory.InvalidateGrab(__instance); } } } } [HarmonyPatch(typeof(PlayerControllerB), "BeginGrabObject")] internal static class LockedFlashlightGrabPatch { [HarmonyPrefix] private static bool AllowGrab(PlayerControllerB __instance) { GrabbableObject currentlyHeldObjectServer = __instance.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)) { return !LightBatAI.IsFlashlightInteractionLocked(val); } return true; } } [HarmonyPatch(typeof(PlayerControllerB), "SwitchToItemSlot")] internal static class LockedFlashlightInventorySlotPatch { [HarmonyPrefix] private static bool AllowSlotSwitch(PlayerControllerB __instance, int slot, GrabbableObject fillSlotWithItem) { if (!((NetworkBehaviour)__instance).IsOwner) { return true; } if ((Object)(object)fillSlotWithItem != (Object)null) { return true; } 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*/)); if (!((Object)(object)val == (Object)null)) { return !LightBatAI.IsFlashlightInteractionLocked(val); } return true; } } [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*/)); if (!((Object)(object)val == (Object)null)) { return !LightBatAI.IsFlashlightInteractionLocked(val); } return true; } } [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; 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; public NavMeshAgent Nav; 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 Vector3 PullRouteDirection; public float NextPullRouteAt; 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; public int Generation; public GameObject AnchorObject; public Transform Anchor; 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; public Light[] Lights; public float[] FullIntensities; } 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; public Vector3 LocalCenter; public Vector3 Extents; } private sealed class BurnMeshState { public SkinnedMeshRenderer BodyRenderer; public SkinnedMeshRenderer EdgeRenderer; public Mesh OriginalMesh; public Mesh BodyMesh; public Mesh EdgeMesh; public int[][] SourceTriangles; public float[][] TriangleScores; public int[][] SortedTriangles; public float[][] SortedScores; public int EdgeMaterialCount; public int[] AppliedBodyCount; public int[] AppliedKeptCount; public bool BurnBuffersReady; } private sealed class BurnMeshAnalysis { public int[][] SourceTriangles; public float[][] TriangleScores; public int[][] SortedTriangles; public float[][] SortedScores; } private sealed class SharedFacilityLightState { public Animator Animator; public Light[] Lights; public float[] FullIntensities; public float RemainingEnergy = 1f; public float FlickerStartedAt; public float FlickerEndsAt; public readonly Dictionary<ulong, int> PerchSlots = new Dictionary<ulong, int>(); public bool? HasOnParameter; } private sealed class FlashlightRaid { public ulong FlashlightId; public FlashlightItem Flashlight; public PlayerControllerB Player; public LightBatAI Volunteer; 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 HandLostSince = -1f; public float ReturnCooldown = 8f; } private sealed class LampVisualState { public Light[] Lights; public float[] FullIntensities; } private sealed class LampValueState { public GrabbableObject Lamp; 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 struct RaidFlashlightSearch { public FlashlightItem? Closest; public NetworkObject? ClosestNetworkObject; public float ClosestDistance; } private readonly struct TargetCandidate { public readonly TargetKind Kind; public readonly int FacilityIndex; public readonly FlashlightItem? Flashlight; public readonly GrabbableObject? Lamp; public readonly Vector3 Position; public readonly float StraightLineDistance; public TargetCandidate(TargetKind kind, int facilityIndex, FlashlightItem? flashlight, GrabbableObject? lamp, Vector3 position, float straightLineDistance) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) Kind = kind; FacilityIndex = facilityIndex; Flashlight = flashlight; Lamp = lamp; Position = position; StraightLineDistance = straightLineDistance; } } private struct TargetChoice { public TargetKind Kind; public int FacilityIndex; public FlashlightItem? Flashlight; public GrabbableObject? Lamp; public Vector3 NavigationPosition; public Vector3 VisualPosition; public float PathDistance; } 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 ApparatusDestinationSampleRadius = 3f; private const float ApparatusPullRouteInterval = 0.1f; 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 RaycastHit[] apparatusLiftProbeHits = (RaycastHit[])(object)new RaycastHit[64]; private static readonly Dictionary<int, bool> apparatusLiftProbeWorldColliders = new Dictionary<int, bool>(); private static readonly Collider[] apparatusDoorProbeColliders = (Collider[])(object)new Collider[256]; private static readonly Dictionary<int, DoorLock?> apparatusDoorColliders = new Dictionary<int, DoorLock>(); private static readonly NavMeshPath apparatusRoutePath = new NavMeshPath(); 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; public AudioClip[] flapSounds; public AudioClip burningSound; public Material burnEdgeMaterial; 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 WeaveProbeInterval = 0.1f; private const float CandidateRangeSlack = 12f; private const int MaxPathChecksPerSearch = 12; private const float ItemScanInterval = 0.5f; 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 RaidHandLossGrace = 0.6f; 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 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 appliedEyeGlow = -1f; private float nextWeaveProbeTime; private float cachedWeaveLimit; private float cachedWeaveSign; private bool boundsFollowSkeleton = true; 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 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 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, BurnMeshAnalysis> burnAnalysisCache = new Dictionary<int, BurnMeshAnalysis>(); private static readonly Dictionary<int, SharedFacilityLightState> sharedFacilityLights = new Dictionary<int, SharedFacilityLightState>(); private static readonly List<LightBatAI> liveBats = new List<LightBatAI>(); private static readonly HashSet<int> raidFlashlightScratch = new HashSet<int>(); private static readonly List<LightBatAI> raidCandidateScratch = new List<LightBatAI>(); private readonly List<TargetCandidate> candidateBuffer = new List<TargetCandidate>(); private NavMeshPath? reusableCandidatePath; private static readonly List<FlashlightItem> cachedFlashlights = new List<FlashlightItem>(); private static readonly List<GrabbableObject> cachedGrabbables = new List<GrabbableObject>(); private static readonly List<LungProp> cachedApparatuses = new List<LungProp>(); private static float itemScanRefreshedAt = -1f; private static readonly RaycastHit[] perchProbeHits = (RaycastHit[])(object)new RaycastHit[32]; private static readonly int FlyStateHash = Animator.StringToHash("Fly"); private static readonly int AttachedToLightStateHash = Animator.StringToHash("AttachedToLight"); private int animatorStateFrame = -1; private AnimatorStateInfo cachedAnimatorState; private bool cachedAnimatorStateValid; private int flightProgressFrame = -1; private float cachedFlightProgress; private static readonly Dictionary<int, Light[]> facilityLightCache = new Dictionary<int, Light[]>(); private static readonly Dictionary<int, Light[]> itemLampLightCache = new Dictionary<int, Light[]>(); private static readonly Dictionary<int, bool> itemLampIdentityCache = new Dictionary<int, bool>(); 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 static Vector3[] pathCornerBuffer = (Vector3[])(object)new Vector3[64]; private bool ApparatusPoseIsGrounded => apparatusGroundPoseApplied; private void ResetApparatusSupportLocally() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) 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(); apparatusDoorColliders.Clear(); apparatusLiftProbeWorldColliders.Clear(); apparatusPullFrame.Clear(); apparatusDrainProgress.Clear(); apparatusLiftStates.Clear(); announcedApparatusDrains.Clear(); apparatusHoldSweepBuffer.Clear(); apparatusLiftSweepBuffer.Clear(); nextApparatusFlockGeneration = 0; } private void ResetSyncedApparatusState() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) 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_009e: 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) 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; NetworkObject val3 = default(NetworkObject); foreach (LungProp cachedApparatus in GetCachedApparatuses()) { if (ApparatusIsAvailable(cachedApparatus) && ((Component)cachedApparatus).TryGetComponent<NetworkObject>(ref val3) && val3.IsSpawned) { float num3 = Vector3.Distance(((Component)this).transform.position, GetApparatusCenter(cachedApparatus)); if (!(num3 >= num2)) { val = cachedApparatus; val2 = val3; 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; for (int i = 0; i < liveBats.Count; i++) { LightBatAI lightBatAI = liveBats[i]; if ((Object)(object)lightBatAI != (Object)null && lightBatAI.CanJoinApparatusFlock(val)) { lightBatAI.JoinApparatusFlock(apparatusFlock); } } if (apparatusFlock.Members.Count == 0) { activeApparatusFlocks.Remove(networkObjectId); return false; } return true; } private bool CanJoinApparatusFlock(LungProp apparatus) { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) if (!((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; if ((Object)(object)playerHeldBy != (Object)null && playerHeldBy.isPlayerControlled && !playerHeldBy.isPlayerDead && playerHeldBy.isInsideFactory) { return !playerHeldBy.isInHangarShipRoom; } return false; } if (((GrabbableObject)apparatus).isInFactory && !((GrabbableObject)apparatus).isInShipRoom) { return !((GrabbableObject)apparatus).isInElevator; } return false; } private static bool ApparatusIsPlayerHeld(LungProp apparatus) { if ((Object)(object)apparatus != (Object)null && ((GrabbableObject)apparatus).isHeld && !((GrabbableObject)apparatus).isPocketed) { return (Object)(object)((GrabbableObject)apparatus).playerHeldBy != (Object)null; } return false; } private static bool ApparatusIsDocked(LungProp apparatus) { if ((Object)(object)apparatus != (Object)null) { if (!apparatus.isLungDocked) { return apparatus.isLungDockedInElevator; } return true; } return false; } 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; } if (((GrabbableObject)apparatus).isInFactory && !((GrabbableObject)apparatus).isInShipRoom) { return ((GrabbableObject)apparatus).isInElevator; } return true; } private void JoinApparatusFlock(ApparatusFlock flock) { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) 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_003d: 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; if (flock != null && !flock.Ending && (Object)(object)flock.Apparatus != (Object)null && flock.Members.Contains(this) && activeApparatusFlocks.TryGetValue(flock.ApparatusId, out ApparatusFlock value)) { return value == flock; } return false; } 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; State state = phase switch { ApparatusPhase.Hauling => State.CarryingApparatus, ApparatusPhase.Draining => State.DrainingApparatus, ApparatusPhase.Perched => State.PerchedOnHeldApparatus, _ => State.FlyingToHeldApparatus, }; 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(state); } } } private void FlyToApparatus() { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_014e: 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_00e5: 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_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_016a: 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_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: 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) 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_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: 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_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_005d: 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) 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_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) StopMoving(); PrepareForFlashlightAttachment(); apparatusActuallyPerched = true; apparatusApproachDetour = Vector3.zero; ApparatusPhase apparatusPhase = ((flock.Phase == ApparatusPhase.Approaching) ? ApparatusPhase.Perched : flock.Phase); PublishApparatusState(flock, apparatusPhase); TransitionTo(apparatusPhase switch { ApparatusPhase.Hauling => State.CarryingApparatus, ApparatusPhase.Draining => State.DrainingApparatus, _ => State.PerchedOnHeldApparatus, }); LockToApparatus(flock.Apparatus, apparatusSlot); } private void UpdateApparatusPull(ApparatusFlock flock, int perched) { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0063: 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_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: 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_00e1: 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_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_007f: 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_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: 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_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_020a: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Unknown result type (might be due to invalid IL or missing references) //IL_022b: Unknown result type (might be due to invalid IL or missing references) //IL_0230: Unknown result type (might be due to invalid IL or missing references) //IL_0247: Unknown result type (might be due to invalid IL or missing references) //IL_024c: Unknown result type (might be due to invalid IL or missing references) //IL_0250: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_0258: Unknown result type (might be due to invalid IL or missing references) //IL_025e: Unknown result type (might be due to invalid IL or missing references) //IL_025f: Unknown result type (might be due to invalid IL or missing references) //IL_0269: Unknown result type (might be due to invalid IL or missing references) //IL_026e: Unknown result type (might be due to invalid IL or missing references) //IL_0274: Unknown result type (might be due to invalid IL or missing references) //IL_02c3: Unknown result type (might be due to invalid IL or missing references) //IL_02ca: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Invalid comparison between Unknown and I4 //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) 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); flock.NextPullRouteAt = 0f; flock.PullRouteDirection = Vector3.zero; } Vector3 val = flock.PullRouteDirection; if (flock.HasPullDestination && flock.NavReady && flock.Nav.isOnNavMesh && Time.time >= flock.NextPullRouteAt) { flock.NextPullRouteAt = Time.time + 0.1f; NavMeshAgent nav = flock.Nav; NavMeshHit val2 = default(NavMeshHit); if (NavMesh.SamplePosition(position, ref val2, 3f, nav.areaMask)) { nav.Warp(((NavMeshHit)(ref val2)).position); } val = Vector3.zero; if (nav.CalculatePath(flock.PullDestination, apparatusRoutePath) && (int)apparatusRoutePath.status != 2) { val = GetFirstMeaningfulPathDirection(apparatusRoutePath, position, 1.4f); } flock.PullRouteDirection = val; } 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 val3 = Vector3.Slerp(flock.PullDirection, val, 1f - Mathf.Exp(-6f * Time.deltaTime)); pullDirection = ((Vector3)(ref val3)).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 (perched > 0) { return perched switch { 1 => 0.7f, 2 => 1.2f, 3 => 1.9f, 4 => 2.5f, _ => 3.1f, }; } return 0f; } private static void ClearApparatusPull(ApparatusFlock flock) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001e: 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_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0020: 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_0071: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) 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_00c0: 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_00df: 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_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) 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_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_012b: 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_012e: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: 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