using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using AdvancedCompany.Game; using AdvancedCompany.Objects; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using GameNetcodeStuff; using GeneralImprovements.API; using HarmonyLib; using LethalLib.Modules; using LethalVRM; using Microsoft.CodeAnalysis; using ModelReplacement; using ModelReplacement.Monobehaviors; using MoreCompany.Cosmetics; using OpenBodyCams.API; using OpenBodyCams.Compatibility; using OpenBodyCams.Components; using OpenBodyCams.Overlay; using OpenBodyCams.Patches; using OpenBodyCams.Utilities; using OpenBodyCams.Utilities.IL; using ReservedItemSlotCore.Data; using ReservedItemSlotCore.Patches; using TMPro; using Unity.Netcode; using Unity.Profiling; using UnityEngine; using UnityEngine.Experimental.Rendering; using UnityEngine.Rendering; using UnityEngine.Rendering.HighDefinition; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("OpenBodyCams")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("OpenBodyCams")] [assembly: AssemblyCopyright("Copyright © 2024")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("3d49e5ff-443d-44f6-90aa-a870ecfeb2d5")] [assembly: AssemblyFileVersion("3.0.11")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("3.0.11.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] [CompilerGenerated] internal sealed class <>z__ReadOnlyArray : IEnumerable, ICollection, IList, IEnumerable, IReadOnlyCollection, IReadOnlyList, ICollection, IList { int ICollection.Count => _items.Length; bool ICollection.IsSynchronized => false; object ICollection.SyncRoot => this; object IList.this[int index] { get { return _items[index]; } set { throw new NotSupportedException(); } } bool IList.IsFixedSize => true; bool IList.IsReadOnly => true; int IReadOnlyCollection.Count => _items.Length; T IReadOnlyList.this[int index] => _items[index]; int ICollection.Count => _items.Length; bool ICollection.IsReadOnly => true; T IList.this[int index] { get { return _items[index]; } set { throw new NotSupportedException(); } } public <>z__ReadOnlyArray(T[] items) { _items = items; } IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)_items).GetEnumerator(); } void ICollection.CopyTo(Array array, int index) { ((ICollection)_items).CopyTo(array, index); } int IList.Add(object value) { throw new NotSupportedException(); } void IList.Clear() { throw new NotSupportedException(); } bool IList.Contains(object value) { return ((IList)_items).Contains(value); } int IList.IndexOf(object value) { return ((IList)_items).IndexOf(value); } void IList.Insert(int index, object value) { throw new NotSupportedException(); } void IList.Remove(object value) { throw new NotSupportedException(); } void IList.RemoveAt(int index) { throw new NotSupportedException(); } IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)_items).GetEnumerator(); } void ICollection.Add(T item) { throw new NotSupportedException(); } void ICollection.Clear() { throw new NotSupportedException(); } bool ICollection.Contains(T item) { return ((ICollection)_items).Contains(item); } void ICollection.CopyTo(T[] array, int arrayIndex) { ((ICollection)_items).CopyTo(array, arrayIndex); } bool ICollection.Remove(T item) { throw new NotSupportedException(); } int IList.IndexOf(T item) { return ((IList)_items).IndexOf(item); } void IList.Insert(int index, T item) { throw new NotSupportedException(); } void IList.RemoveAt(int index) { throw new NotSupportedException(); } } namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class IsUnmanagedAttribute : Attribute { } [CompilerGenerated] [Microsoft.CodeAnalysis.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] [Microsoft.CodeAnalysis.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] [Microsoft.CodeAnalysis.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 OpenBodyCams { public class BodyCamComponent : MonoBehaviour { public delegate bool TargetChangedToTransform(MonoBehaviour bodyCam, Transform target, ref Transform attachmentPoint, ref Vector3 offset, ref Quaternion angle, ref Renderer[] renderersToHide); public delegate void RenderersToHideTransformer(MonoBehaviour bodyCam, ref Renderer[] renderers); [Flags] private enum TargetDirtyStatus { None = 0, Immediate = 1, UntilRender = 2 } private const float RADAR_BOOSTER_INITIAL_PAN = 270f; private static readonly Vector3 BODY_CAM_OFFSET = new Vector3(0.07f, 0f, 0.16f); private static readonly Vector3 PLAYER_HEAD_CAM_OFFSET = new Vector3(0.07f, 0f, 0.125f); private static readonly Vector3 CORPSE_HEAD_CAM_OFFSET = new Vector3(0.07f, -0.1f, 0.125f); private static readonly Vector3 MASKED_HEAD_CAM_OFFSET = new Vector3(0.07f, 0.1f, 0.031f); private static readonly int CullModeProperty = Shader.PropertyToID("_CullMode"); private static int bodyCamCullingMask; private static FrameSettings mainCameraCustomFrameSettings; private static FrameSettingsOverrideMask mainCameraCustomFrameSettingsMask; private static Material fogShaderMaterial; private static GameObject nightVisionPrefab; private static BodyCamComponent[] AllBodyCams = Array.Empty(); private static BodyCamComponent lastBodyCamCulled; private static BodyCamComponent lastBodyCamRendered; private static Transform sunRootTransform = null; private static MatchLocalPlayerPosition[] matchLocalPlayerPositions = Array.Empty(); internal static WeatherEffectComponents[] weatherEffects = Array.Empty(); private static bool disableCameraWhileTargetIsOnShip = false; private static float radarBoosterPanSpeed; private Transform CameraContainer; internal Transform CameraTransform; internal Camera Camera; internal Renderer MonitorRenderer; internal int MonitorMaterialIndex = -1; internal Material MonitorOnMaterial; internal Material MonitorNoTargetMaterial; internal Material MonitorOffMaterial; internal Material MonitorDisabledMaterial; internal bool MonitorIsOn = true; internal bool EnableCamera = true; private bool keepCameraOn; private static readonly Vector2Int DefaultResolution = new Vector2Int(160, 120); private Vector2Int resolution = DefaultResolution; private bool isRemoteCamera = true; private PlayerModelState localPlayerModelState; private PlayerControllerB currentPlayer; private PlayerModelState currentPlayerModelState; private Transform currentActualTarget; private Transform currentAttachmentPoint; private Renderer[] currentRenderersToHide = Array.Empty(); private Material currentObstructingMaterial; private float currentObstructingMaterialCullMode; private bool originalDirectSunlightEnabled; private bool originalIndirectSunlightEnabled; private bool targetSunlightEnabled = true; private float originalBlackSkyVolumeWeight; private float targetBlackSkyVolumeWeight; private float originalIndirectSunlightDimmer; private float targetIndirectSunlightDimmer; private Vector3 originalSunRootScale = Vector3.one; private Transform targetWeatherParent; private WeatherEffectComponents[] targetWeatherComponents; private Light nightVisionLight; private MeshRenderer greenFlashRenderer; private Animator greenFlashAnimator; private MeshRenderer fogShaderPlaneRenderer; private TargetDirtyStatus targetDirtyStatus; private float elapsedSinceLastFrame; private float timePerFrame; private bool panCamera; private float panAngle = 270f; private CameraRenderingStatus cameraStatus; private const string profilerMarkerPrefix = "OpenBodyCams:"; private static readonly ProfilerMarker markerRevertCullingOverrides = new ProfilerMarker("OpenBodyCams:RevertCullingOverrides"); private static readonly ProfilerMarker markerBeforeCullingAnyCamera = new ProfilerMarker("OpenBodyCams:BeforeCullingAnyCamera"); private static readonly ProfilerMarker markerBeforeRenderingAnyCamera = new ProfilerMarker("OpenBodyCams:BeforeRenderingAnyCamera"); private static readonly ProfilerMarker markerAfterRenderingAnyCamera = new ProfilerMarker("OpenBodyCams:AfterRenderingAnyCamera"); private static readonly ProfilerMarker markerApplyCullingOverrides = new ProfilerMarker("OpenBodyCams:ApplyCullingOverrides"); private static readonly ProfilerMarker markerApplyViewPerspective = new ProfilerMarker("OpenBodyCams:ViewPerspective.Apply"); public bool IsRemoteCamera { get { return isRemoteCamera; } set { if (isRemoteCamera != value) { isRemoteCamera = value; TargetHasChanged(); } } } public bool ForceEnableCamera { get { return keepCameraOn; } set { keepCameraOn = value; } } public Vector2Int Resolution { get { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return resolution; } set { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) resolution = value; UpdateSettings(); } } public bool IsBlanked => !CameraShouldRender(cameraStatus); public CameraRenderingStatus CameraStatus => cameraStatus; public bool ForceTargetInvalid { get; set; } public float Framerate { get { return 1f / timePerFrame; } set { if (value != 0f) { timePerFrame = 1f / value; } else { timePerFrame = 0f; } } } public PlayerControllerB? CurrentPlayerTarget => currentPlayer; public Transform? CurrentTarget => currentActualTarget; public static event TargetChangedToTransform? BeforeTargetChangedToTransform; public static event RenderersToHideTransformer? RenderersToHideTransformers; public event Action? OnCameraCreated; public event Action? OnRenderTextureCreated; public event Action? OnBlankedSet; public event Action? OnCameraStatusChanged; public event Action? OnScreenPowerChanged; public event BodyCam.BodyCamStatusUpdate? OnTargetChanged; public static BodyCamComponent[] GetAllBodyCams() { return AllBodyCams.ToArray(); } public Camera? GetCamera() { CreateCameraIfNotCreated(); return Camera; } internal static void InitializeStatic() { SceneManager.sceneLoaded += delegate { UpdateSceneStaticObjects(); }; SceneManager.sceneUnloaded += delegate { UpdateSceneStaticObjects(); }; } private static void UpdateSceneStaticObjects() { animatedSun obj = Object.FindAnyObjectByType(); object obj2; if (obj == null) { obj2 = null; } else { MatchLocalPlayerPosition componentInParent = ((Component)obj).GetComponentInParent(); obj2 = ((componentInParent != null) ? ((Component)componentInParent).transform : null); } sunRootTransform = (Transform)obj2; matchLocalPlayerPositions = Object.FindObjectsByType((FindObjectsSortMode)0); } internal static void UpdateWeathers() { if ((Object)(object)TimeOfDay.Instance != (Object)null) { int num = TimeOfDay.Instance.effects.Length; weatherEffects = new WeatherEffectComponents[num]; for (int i = 0; i < num; i++) { weatherEffects[i] = new WeatherEffectComponents((LevelWeatherType)i); } } else { weatherEffects = Array.Empty(); } CreateTargetWeatherEffectsForAllCams(); } internal static void InitializeAtStartOfGame() { //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) PlayerControllerB val = StartOfRound.Instance.allPlayerScripts[0]; bodyCamCullingMask = val.gameplayCamera.cullingMask & ~LayerMask.GetMask(new string[3] { "Ignore Raycast", "UI", "HelmetVisor" }); HDAdditionalCameraData component = ((Component)val.gameplayCamera).GetComponent(); if (component.customRenderingSettings) { Plugin.Instance.Logger.LogInfo((object)("Using custom camera settings from " + ((Object)component).name + ".")); mainCameraCustomFrameSettings = component.renderingPathCustomFrameSettings; mainCameraCustomFrameSettingsMask = component.renderingPathCustomFrameSettingsOverrideMask; } fogShaderMaterial = ((Renderer)((Component)((Component)val.localVisor).transform.Find("ScavengerHelmet/Plane")).GetComponent()).sharedMaterial; nightVisionPrefab = Object.Instantiate(((Component)val.nightVision).gameObject); ((Object)nightVisionPrefab).hideFlags = (HideFlags)61; ((Object)nightVisionPrefab).name = "NightVision"; nightVisionPrefab.transform.localPosition = Vector3.zero; nightVisionPrefab.SetActive(false); Light component2 = nightVisionPrefab.GetComponent(); ((Behaviour)component2).enabled = false; UpdateAllCameraSettings(); } internal static bool HasFinishedGameStartSetup() { return (Object)(object)nightVisionPrefab != (Object)null; } public static void UpdateAllCameraSettings() { UpdateStaticSettings(); BodyCamComponent[] allBodyCams = AllBodyCams; foreach (BodyCamComponent bodyCamComponent in allBodyCams) { bodyCamComponent.UpdateSettings(); } } internal static void UpdateStaticSettings() { disableCameraWhileTargetIsOnShip = Plugin.DisableCameraWhileTargetIsOnShip.Value; radarBoosterPanSpeed = Plugin.RadarBoosterPanRPM.Value * 360f / 60f; } internal static void CreateTargetWeatherEffectsForAllCams() { BodyCamComponent[] allBodyCams = AllBodyCams; foreach (BodyCamComponent bodyCamComponent in allBodyCams) { bodyCamComponent.CreateTargetWeatherEffects(); } } public static void MarkTargetDirtyUntilRenderForAllBodyCams(Transform target) { BodyCamComponent[] allBodyCams = AllBodyCams; foreach (BodyCamComponent bodyCamComponent in allBodyCams) { bodyCamComponent.MarkTargetDirtyUntilRender(target); } } public static void MarkAnyParentDirtyUntilRenderForAllBodyCams(Transform target) { while ((Object)(object)target != (Object)null) { MarkTargetDirtyUntilRenderForAllBodyCams(target); target = target.parent; } } public static void MarkTargetDirtyUntilRenderForAllBodyCams() { BodyCamComponent[] allBodyCams = AllBodyCams; foreach (BodyCamComponent bodyCamComponent in allBodyCams) { bodyCamComponent.MarkTargetDirtyUntilRender(); } } public static void MarkTargetStatusChangedForAllBodyCams(Transform target) { BodyCamComponent[] allBodyCams = AllBodyCams; foreach (BodyCamComponent bodyCamComponent in allBodyCams) { bodyCamComponent.MarkTargetStatusChanged(target); } } public static void MarkTargetStatusChangedForAllBodyCams() { BodyCamComponent[] allBodyCams = AllBodyCams; foreach (BodyCamComponent bodyCamComponent in allBodyCams) { bodyCamComponent.MarkTargetStatusChanged(); } } private static void RevertLastOverrides() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) ProfilerMarker val = markerRevertCullingOverrides; AutoScope val2 = ((ProfilerMarker)(ref val)).Auto(); try { if ((Object)(object)lastBodyCamCulled != (Object)null) { lastBodyCamCulled.RevertCullingOverrides(); lastBodyCamCulled = null; } if ((Object)(object)lastBodyCamRendered != (Object)null) { lastBodyCamRendered.RevertRenderingOverrides(); lastBodyCamRendered = null; } } finally { ((IDisposable)(AutoScope)(ref val2)).Dispose(); } } internal static void BeforeCullingAnyCamera(Camera camera) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) ProfilerMarker val = markerBeforeCullingAnyCamera; ((ProfilerMarker)(ref val)).Begin((Object)(object)camera); RevertLastOverrides(); int num = AllBodyCams.Length; for (int i = 0; i < num; i++) { BodyCamComponent bodyCamComponent = AllBodyCams[i]; if (bodyCamComponent.Camera == camera) { lastBodyCamCulled = bodyCamComponent; bodyCamComponent.ApplyCullingOverrides(); break; } } val = markerBeforeCullingAnyCamera; ((ProfilerMarker)(ref val)).End(); } internal static void BeforeRenderingAnyCamera(Camera camera) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) ProfilerMarker val = markerBeforeRenderingAnyCamera; ((ProfilerMarker)(ref val)).Begin((Object)(object)camera); RevertLastOverrides(); int num = AllBodyCams.Length; for (int i = 0; i < num; i++) { BodyCamComponent bodyCamComponent = AllBodyCams[i]; if (bodyCamComponent.Camera == camera) { lastBodyCamRendered = bodyCamComponent; bodyCamComponent.ApplyRenderingOverrides(); break; } } val = markerBeforeRenderingAnyCamera; ((ProfilerMarker)(ref val)).End(); } internal static void AfterRenderingAnyCamera(Camera camera) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) ProfilerMarker val = markerAfterRenderingAnyCamera; ((ProfilerMarker)(ref val)).Begin((Object)(object)camera); RevertLastOverrides(); val = markerAfterRenderingAnyCamera; ((ProfilerMarker)(ref val)).End(); } private void Awake() { if (!HasFinishedGameStartSetup()) { Plugin.Instance.Logger.LogError((object)"Attempted to create a body cam before static initialization has been completed."); Plugin.Instance.Logger.LogError((object)"This may occur if the save is corrupted, or if a mod caused an error during the start of the game."); Object.Destroy((Object)(object)this); return; } BodyCamComponent[] allBodyCams = AllBodyCams; int num = 0; BodyCamComponent[] array = new BodyCamComponent[1 + allBodyCams.Length]; ReadOnlySpan readOnlySpan = new ReadOnlySpan(allBodyCams); readOnlySpan.CopyTo(new Span(array).Slice(num, readOnlySpan.Length)); num += readOnlySpan.Length; array[num] = this; AllBodyCams = array; BodyCam.BodyCamInstantiated(this); } private void Start() { if (HasFinishedGameStartSetup()) { CreateCameraIfNotCreated(); CreateTargetWeatherEffects(); SyncBodyCamToRadarMap.UpdateBodyCamTarget(this); } } private void SetMonitorMaterial(Material material) { if (!((Object)(object)MonitorRenderer == (Object)null)) { MonitorRenderer.SetMaterial(MonitorMaterialIndex, material); } } private void EnsureMaterialsExist() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown //IL_004e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)MonitorOnMaterial == (Object)null) { MonitorOnMaterial = new Material(Shader.Find("HDRP/Unlit")) { name = "BodyCamMaterial" }; MonitorOnMaterial.SetFloat("_AlbedoAffectEmissive", 1f); MonitorOnMaterial.SetColor("_EmissiveColor", Color.white); } if ((Object)(object)MonitorOffMaterial == (Object)null) { MonitorOffMaterial = ShipObjects.BlackScreenMaterial; } } private void CreateCameraIfNotCreated() { //IL_004f: 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_0069: Expected O, but got Unknown //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Expected O, but got Unknown //IL_019c: 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_029b: Unknown result type (might be due to invalid IL or missing references) //IL_02bb: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)Camera != (Object)null)) { Plugin.Instance.Logger.LogInfo((object)("Creating a new camera for " + ((Object)this).name + ".")); UpdateScreenMaterial(); CameraContainer = new GameObject("BodyCam_" + ((Object)this).name + "_Container").transform; GameObject val = new GameObject("BodyCam"); CameraTransform = val.transform; CameraTransform.SetParent(CameraContainer, false); Camera = val.AddComponent(); Camera.nearClipPlane = 0.01f; Camera.cullingMask = bodyCamCullingMask; HDAdditionalCameraData val2 = val.AddComponent(); val2.volumeLayerMask = LayerMask.op_Implicit(1); _ = mainCameraCustomFrameSettings; val2.customRenderingSettings = true; ref FrameSettings renderingPathCustomFrameSettings = ref val2.renderingPathCustomFrameSettings; ref FrameSettingsOverrideMask renderingPathCustomFrameSettingsOverrideMask = ref val2.renderingPathCustomFrameSettingsOverrideMask; renderingPathCustomFrameSettings = mainCameraCustomFrameSettings; renderingPathCustomFrameSettingsOverrideMask = mainCameraCustomFrameSettingsMask; ((FrameSettings)(ref renderingPathCustomFrameSettings)).SetEnabled((FrameSettingsField)93, false); ((BitArray128)(ref renderingPathCustomFrameSettingsOverrideMask.mask))[93u] = true; ((FrameSettings)(ref renderingPathCustomFrameSettings)).SetEnabled((FrameSettingsField)88, false); ((BitArray128)(ref renderingPathCustomFrameSettingsOverrideMask.mask))[88u] = true; val2.hasPersistentHistory = true; GameObject val3 = Object.Instantiate(nightVisionPrefab); val3.transform.SetParent(CameraTransform, false); val3.SetActive(true); nightVisionLight = val3.GetComponent(); UpdateSettings(); GameObject val4 = new GameObject("CameraGreenTransitionScaler"); val4.transform.SetParent(CameraTransform, false); val4.transform.localScale = new Vector3(1f, 0.004f, 1f); GameObject val5 = Object.Instantiate(((Component)StartOfRound.Instance.mapScreen.mapCameraAnimator).gameObject); val5.transform.SetParent(val4.transform, false); val5.transform.localPosition = new Vector3(0f, 0f, 0.1f); val5.layer = 0; greenFlashRenderer = val5.GetComponent(); ((Renderer)greenFlashRenderer).forceRenderingOff = true; greenFlashAnimator = val5.GetComponent() ?? throw new Exception("Green flash object copied from the map screen has no Animator."); greenFlashAnimator.Play("MapTransitionGreen", 0, 1f); greenFlashAnimator.WriteDefaultValues(); GameObject val6 = GameObject.CreatePrimitive((PrimitiveType)5); Object.Destroy((Object)(object)val6.GetComponent()); val6.transform.SetParent(CameraTransform, false); val6.transform.localPosition = new Vector3(0f, 0f, Camera.nearClipPlane * 2f); val6.transform.localRotation = Quaternion.Euler(0f, 0f, 0f); fogShaderPlaneRenderer = val6.GetComponent(); ((Renderer)fogShaderPlaneRenderer).sharedMaterial = fogShaderMaterial; ((Renderer)fogShaderPlaneRenderer).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)fogShaderPlaneRenderer).receiveShadows = false; ((Renderer)fogShaderPlaneRenderer).forceRenderingOff = true; this.OnCameraCreated?.Invoke(Camera); } } private bool PositionIsInInterior(Vector3 position) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return position.y < -80f; } private void CreateTargetWeatherEffects() { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Invalid comparison between Unknown and I4 //IL_0167: Unknown result type (might be due to invalid IL or missing references) DestroyTargetWeatherEffects(); if (Plugin.DisplayWeatherBasedOnPerspective.Value != BoolWithDefault.True) { return; } targetWeatherComponents = new WeatherEffectComponents[weatherEffects.Length]; targetWeatherParent = new GameObject("BodyCam_" + ((Object)this).name + "_TargetWeathers").transform; TimeOfDay instance = TimeOfDay.Instance; LevelWeatherType val = (LevelWeatherType)((instance == null) ? (-1) : ((int)instance.currentLevelWeather)); Dictionary dictionary = new Dictionary(); for (int i = 0; i < targetWeatherComponents.Length; i++) { WeatherEffectComponents weatherEffectComponents = weatherEffects[i]; GameObject value = null; if ((Object)(object)weatherEffectComponents.effectObject != (Object)null && !dictionary.TryGetValue(weatherEffectComponents.effectObject, out value)) { value = Object.Instantiate(weatherEffectComponents.effectObject); value.transform.SetParent(targetWeatherParent, false); OccludeAudio[] componentsInChildren = value.GetComponentsInChildren(); foreach (OccludeAudio val2 in componentsInChildren) { Object.Destroy((Object)(object)val2); } AudioLowPassFilter[] componentsInChildren2 = value.GetComponentsInChildren(); foreach (AudioLowPassFilter val3 in componentsInChildren2) { Object.Destroy((Object)(object)val3); } AudioSource[] componentsInChildren3 = value.GetComponentsInChildren(); foreach (AudioSource val4 in componentsInChildren3) { Object.Destroy((Object)(object)val4); } dictionary.Add(weatherEffectComponents.effectObject, value); } WeatherEffectComponents weatherEffectComponents2 = new WeatherEffectComponents(weatherEffectComponents.weatherType, value); weatherEffectComponents2.SetVisibility(show: false); if ((int)val == i && !PositionIsInInterior(CameraTransform.position)) { weatherEffectComponents2.enabled = true; } targetWeatherComponents[i] = weatherEffectComponents2; } } private void DestroyTargetWeatherEffects() { targetWeatherComponents = Array.Empty(); if ((Object)(object)targetWeatherParent != (Object)null) { Object.Destroy((Object)(object)((Component)targetWeatherParent).gameObject); } targetWeatherParent = null; } public void UpdateSettings() { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown if (!((Object)(object)Camera == (Object)null)) { int x = ((Vector2Int)(ref resolution)).x; int y = ((Vector2Int)(ref resolution)).y; Camera.targetTexture = new RenderTexture(x, y, 32) { name = ((Object)this).name + ".RenderTexture", filterMode = Plugin.MonitorTextureFiltering.Value }; Camera.fieldOfView = Plugin.FieldOfView.Value; if ((Object)(object)MonitorOnMaterial != (Object)null) { MonitorOnMaterial.mainTexture = (Texture)(object)Camera.targetTexture; } Camera.farClipPlane = Plugin.RenderDistance.Value; nightVisionLight.intensity = 367f * Plugin.NightVisionBrightness.Value; nightVisionLight.range = 12f * Plugin.NightVisionBrightness.Value; this.OnRenderTextureCreated?.Invoke(Camera.targetTexture); CreateTargetWeatherEffects(); } } public void StartTargetTransition() { if (Plugin.UseTargetTransitionAnimation.Value) { Animator obj = greenFlashAnimator; if (obj != null) { obj.SetTrigger("Transition"); } } } public void UpdateScreenMaterial() { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) if (!HasFinishedGameStartSetup()) { return; } EnsureMaterialsExist(); if (!MonitorIsOn) { if ((Object)(object)MonitorOffMaterial != (Object)null) { SetMonitorMaterial(MonitorOffMaterial); } return; } bool enabled = ((Behaviour)this).enabled; if (IsBlanked || !enabled) { MonitorOnMaterial.color = Color.black; if (!enabled && (Object)(object)MonitorDisabledMaterial != (Object)null) { SetMonitorMaterial(MonitorDisabledMaterial); return; } if ((Object)(object)MonitorNoTargetMaterial != (Object)null) { SetMonitorMaterial(MonitorNoTargetMaterial); return; } } else { MonitorOnMaterial.color = Color.white; } SetMonitorMaterial(MonitorOnMaterial); } public void SetScreenPowered(bool powered) { if (!((Object)(object)MonitorRenderer == (Object)null) && powered != MonitorIsOn) { if (powered) { StartTargetTransition(); } MonitorIsOn = powered; UpdateScreenMaterial(); this.OnScreenPowerChanged?.Invoke(MonitorIsOn); } } public bool IsScreenPowered() { return MonitorIsOn; } private bool CameraShouldRender(CameraRenderingStatus status) { return status == CameraRenderingStatus.Rendering; } private void SetStatus(CameraRenderingStatus newStatus) { if (newStatus != cameraStatus) { bool flag = CameraShouldRender(cameraStatus) != CameraShouldRender(newStatus); cameraStatus = newStatus; UpdateScreenMaterial(); if (flag) { this.OnBlankedSet?.Invoke(IsBlanked); } this.OnCameraStatusChanged?.Invoke(cameraStatus); } } private CameraRenderingStatus GetUpdatedCameraStatus() { //IL_00f0: Unknown result type (might be due to invalid IL or missing references) if (!EnableCamera) { return CameraRenderingStatus.Disabled; } if ((Object)(object)currentActualTarget == (Object)null || ForceTargetInvalid) { return CameraRenderingStatus.TargetInvalid; } if (currentPlayer != null) { if (currentPlayer.isPlayerControlled) { if (currentPlayer.isInHangarShipRoom) { return CameraRenderingStatus.TargetDisabledOnShip; } return CameraRenderingStatus.Rendering; } if (!currentPlayer.isPlayerDead) { return CameraRenderingStatus.Rendering; } if ((Object)(object)currentPlayer.redirectToEnemy != (Object)null) { if (currentPlayer.redirectToEnemy.isInsidePlayerShip) { return CameraRenderingStatus.TargetDisabledOnShip; } return CameraRenderingStatus.Rendering; } if ((Object)(object)currentPlayer.deadBody != (Object)null) { if (!((Component)currentPlayer.deadBody).gameObject.activeSelf) { return CameraRenderingStatus.TargetInvalid; } if (currentPlayer.deadBody.isInShip) { return CameraRenderingStatus.TargetDisabledOnShip; } return CameraRenderingStatus.Rendering; } } RadarBoosterItem component = ((Component)currentActualTarget).GetComponent(); if (component != null) { Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(3000f, -400f, 3000f); if (((Vector3)(ref ((GrabbableObject)component).targetFloorPosition)).Equals(val)) { return CameraRenderingStatus.TargetInvalid; } if (((GrabbableObject)component).isInShipRoom) { return CameraRenderingStatus.TargetDisabledOnShip; } return CameraRenderingStatus.Rendering; } return CameraRenderingStatus.Rendering; } private static void CollectDescendentModelsToHide(Transform parent, List list) { //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Expected O, but got Unknown BodyCamComponent[] allBodyCams = AllBodyCams; foreach (BodyCamComponent bodyCamComponent in allBodyCams) { if ((Object)(object)parent == (Object)(object)bodyCamComponent.CameraTransform) { return; } } Renderer component = ((Component)parent).GetComponent(); if ((Object)(object)component != (Object)null && ((1 << ((Component)component).gameObject.layer) & bodyCamCullingMask) != 0) { list.Add(component); } foreach (Transform item in parent) { Transform parent2 = item; CollectDescendentModelsToHide(parent2, list); } } private static Renderer[] CollectModelsToHide(Transform parent) { List list = new List(20); CollectDescendentModelsToHide(parent, list); return list.ToArray(); } private bool TargetWouldRequireUpdate(Transform target) { if (target == null) { return true; } if (currentActualTarget == target) { return true; } if (((Component)StartOfRound.Instance.localPlayerController).transform == target) { return true; } return false; } public void MarkTargetStatusChanged(Transform transform) { if (!targetDirtyStatus.HasFlag(TargetDirtyStatus.Immediate) && TargetWouldRequireUpdate(transform)) { targetDirtyStatus |= TargetDirtyStatus.Immediate; } } public void MarkTargetStatusChanged() { MarkTargetStatusChanged(null); } public void MarkTargetDirtyUntilRender(Transform transform) { if (!targetDirtyStatus.HasFlag(TargetDirtyStatus.UntilRender) && TargetWouldRequireUpdate(transform)) { targetDirtyStatus |= TargetDirtyStatus.UntilRender; } } public void MarkTargetDirtyUntilRender() { MarkTargetDirtyUntilRender(null); } private void ClearTargetDirtyImmediate() { targetDirtyStatus &= ~TargetDirtyStatus.Immediate; } private void SetRenderersToHide(Renderer[] renderers) { BodyCamComponent.RenderersToHideTransformers?.Invoke((MonoBehaviour)(object)this, ref renderers); currentRenderersToHide = renderers; } private void TargetHasChanged() { UpdateOverrides(float.PositiveInfinity); this.OnTargetChanged?.Invoke((MonoBehaviour)(object)this); } public void SetTargetToNone() { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) CreateCameraIfNotCreated(); ClearTargetDirtyImmediate(); currentPlayer = null; currentActualTarget = null; currentAttachmentPoint = null; SetRenderersToHide(Array.Empty()); UpdateModelReferences(); currentObstructingMaterial = null; CameraTransform.SetLocalPositionAndRotation(Vector3.zero, Quaternion.identity); TargetHasChanged(); } public void SetTargetToPlayer(PlayerControllerB player) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_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_0253: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: 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_0126: 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_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) CreateCameraIfNotCreated(); if ((Object)(object)player == (Object)null) { SetTargetToNone(); return; } ClearTargetDirtyImmediate(); currentPlayer = player; currentActualTarget = null; currentAttachmentPoint = null; UpdateModelReferences(); panCamera = false; currentObstructingMaterial = null; Vector3 val = Vector3.zero; if (!currentPlayer.isPlayerDead) { if (Plugin.CameraMode.Value == CameraModeOptions.Head) { currentAttachmentPoint = ((Component)currentPlayer.gameplayCamera).transform; val = PLAYER_HEAD_CAM_OFFSET; } else { currentAttachmentPoint = ((Component)currentPlayer.playerGlobalHead).transform.parent; val = BODY_CAM_OFFSET; } currentActualTarget = ((Component)currentPlayer).transform; SetRenderersToHide(Array.Empty()); } else if ((Object)(object)currentPlayer.redirectToEnemy != (Object)null) { EnemyAI redirectToEnemy = currentPlayer.redirectToEnemy; MaskedPlayerEnemy val2 = (MaskedPlayerEnemy)(object)((redirectToEnemy is MaskedPlayerEnemy) ? redirectToEnemy : null); if (val2 != null) { if (Plugin.CameraMode.Value == CameraModeOptions.Head) { currentAttachmentPoint = ((EnemyAI)val2).eye; val = MASKED_HEAD_CAM_OFFSET; } else { currentAttachmentPoint = val2.animationContainer.Find("metarig/spine/spine.001/spine.002/spine.003"); val = BODY_CAM_OFFSET; } } else { currentAttachmentPoint = currentPlayer.redirectToEnemy.eye; } currentActualTarget = ((Component)currentPlayer.redirectToEnemy).transform; SetRenderersToHide(CollectModelsToHide(currentActualTarget)); } else if ((Object)(object)currentPlayer.deadBody != (Object)null) { Transform parent; if (Plugin.CameraMode.Value == CameraModeOptions.Head) { currentAttachmentPoint = ((Component)currentPlayer.deadBody).transform.Find("spine.001/spine.002/spine.003/spine.004/spine.004_end"); parent = currentAttachmentPoint.parent; val = CORPSE_HEAD_CAM_OFFSET; } else { currentAttachmentPoint = ((Component)currentPlayer.deadBody).transform.Find("spine.001/spine.002/spine.003"); parent = currentAttachmentPoint; val = BODY_CAM_OFFSET; } currentActualTarget = ((Component)currentPlayer.deadBody).transform; SetRenderersToHide(CollectModelsToHide(parent)); Renderer component = ((Component)currentActualTarget).GetComponent(); currentObstructingMaterial = ((component != null) ? component.sharedMaterial : null); } if ((Object)(object)currentAttachmentPoint == (Object)null) { currentAttachmentPoint = currentActualTarget; } CameraTransform.SetLocalPositionAndRotation(val, Quaternion.identity); TargetHasChanged(); } public void SetTargetToTransform(Transform transform) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) CreateCameraIfNotCreated(); if ((Object)(object)transform == (Object)null || (Object)(object)((Component)transform).gameObject == (Object)null) { SetTargetToNone(); return; } ClearTargetDirtyImmediate(); currentPlayer = null; currentActualTarget = transform; currentAttachmentPoint = null; UpdateModelReferences(); panCamera = false; Vector3 offset = Vector3.zero; Quaternion angle = Quaternion.identity; currentRenderersToHide = Array.Empty(); RadarBoosterItem component = ((Component)currentActualTarget).GetComponent(); if (component != null) { SetRenderersToHide((Renderer[])(object)new Renderer[1] { ((Component)((Component)currentActualTarget).transform.Find("AnimContainer/Rod")).GetComponent() }); currentAttachmentPoint = currentActualTarget; ((Vector3)(ref offset))..ctor(0f, 1.5f, 0f); panCamera = true; } else { currentAttachmentPoint = currentActualTarget; if (BodyCamComponent.BeforeTargetChangedToTransform != null) { Delegate[] invocationList = BodyCamComponent.BeforeTargetChangedToTransform.GetInvocationList(); foreach (Delegate @delegate in invocationList) { if (((TargetChangedToTransform)@delegate)((MonoBehaviour)(object)this, currentActualTarget, ref currentAttachmentPoint, ref offset, ref angle, ref currentRenderersToHide)) { SetRenderersToHide(currentRenderersToHide); break; } } } } CameraTransform.SetLocalPositionAndRotation(offset, angle); TargetHasChanged(); } private void UpdateTargetStatus() { if ((Object)(object)currentPlayer != (Object)null) { SetTargetToPlayer(currentPlayer); } else { SetTargetToTransform(currentActualTarget); } } private void UpdateModelReferences() { ViewPerspective.PrepareModelState(currentPlayer, ref currentPlayerModelState); if ((Object)(object)currentPlayer != (Object)(object)StartOfRound.Instance.localPlayerController) { ViewPerspective.PrepareModelState(StartOfRound.Instance.localPlayerController, ref localPlayerModelState); } } private void UpdateTargetStatusBeforeRender() { if (targetDirtyStatus.HasFlag(TargetDirtyStatus.UntilRender)) { UpdateTargetStatus(); targetDirtyStatus ^= TargetDirtyStatus.UntilRender; } } private void SetTargetWeathersVisible(bool visible) { for (int i = 0; i < targetWeatherComponents.Length; i++) { WeatherEffectComponents weatherEffectComponents = weatherEffects[i]; WeatherEffectComponents weatherEffectComponents2 = targetWeatherComponents[i]; if (weatherEffectComponents != null && weatherEffectComponents2 != null) { weatherEffectComponents.SetVisibility(!visible); weatherEffectComponents2.SetVisibility(visible); } } } private static void SetMatchLocalPlayerPositions(Vector3 position) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) MatchLocalPlayerPosition[] array = matchLocalPlayerPositions; foreach (MatchLocalPlayerPosition val in array) { if (!((Object)(object)val == (Object)null)) { ((Component)val).transform.position = position; } } } private void ApplyCullingOverrides() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: 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_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0256: Unknown result type (might be due to invalid IL or missing references) //IL_0211: Unknown result type (might be due to invalid IL or missing references) //IL_0216: Unknown result type (might be due to invalid IL or missing references) //IL_0221: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) ProfilerMarker val = markerApplyCullingOverrides; AutoScope val2 = ((ProfilerMarker)(ref val)).Auto(); try { UpdateTargetStatusBeforeRender(); if ((Object)(object)currentAttachmentPoint == (Object)null) { return; } PlayerControllerB localPlayerController = StartOfRound.Instance.localPlayerController; if ((Object)(object)localPlayerController == (Object)null) { return; } CameraContainer.SetPositionAndRotation(currentAttachmentPoint.position, currentAttachmentPoint.rotation); ((Behaviour)nightVisionLight).enabled = true; ((Renderer)greenFlashRenderer).forceRenderingOff = false; ((Renderer)fogShaderPlaneRenderer).forceRenderingOff = false; val = markerApplyViewPerspective; AutoScope val3 = ((ProfilerMarker)(ref val)).Auto(); try { ViewPerspective.Apply(ref currentPlayerModelState, Perspective.FirstPerson); if (currentPlayer != localPlayerController) { ViewPerspective.Apply(ref localPlayerModelState, Perspective.ThirdPerson); } } finally { ((IDisposable)(AutoScope)(ref val3)).Dispose(); } bool flag = false; Renderer[] array = currentRenderersToHide; foreach (Renderer val4 in array) { if ((Object)(object)val4 == (Object)null) { if (!flag) { Plugin.Instance.Logger.LogError((object)("Mesh on " + ((Object)currentActualTarget).name + " that would obstruct the " + ((Object)this).name + " body cam was unexpectedly null.")); } flag = true; } else { val4.forceRenderingOff = true; } } if ((Object)(object)currentObstructingMaterial != (Object)null) { currentObstructingMaterialCullMode = currentObstructingMaterial.GetFloat(CullModeProperty); currentObstructingMaterial.SetFloat(CullModeProperty, 2f); } Light sunDirect = TimeOfDay.Instance.sunDirect; if ((Object)(object)sunDirect != (Object)null) { Light sunIndirect = TimeOfDay.Instance.sunIndirect; originalDirectSunlightEnabled = ((Behaviour)sunDirect).enabled; originalIndirectSunlightEnabled = ((Behaviour)sunIndirect).enabled; ((Behaviour)sunDirect).enabled = targetSunlightEnabled; ((Behaviour)sunIndirect).enabled = targetSunlightEnabled; } Volume blackSkyVolume = StartOfRound.Instance.blackSkyVolume; originalBlackSkyVolumeWeight = blackSkyVolume.weight; blackSkyVolume.weight = targetBlackSkyVolumeWeight; if ((Object)(object)sunRootTransform != (Object)null) { originalSunRootScale = sunRootTransform.localScale; Transform obj = sunRootTransform; obj.localScale *= Math.Min(Camera.farClipPlane * 0.005f, 1f); } SetMatchLocalPlayerPositions(((Component)Camera).transform.position); SetTargetWeathersVisible(visible: true); } finally { ((IDisposable)(AutoScope)(ref val2)).Dispose(); } } private void RevertCullingOverrides() { //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)currentAttachmentPoint == (Object)null) { return; } PlayerControllerB localPlayerController = StartOfRound.Instance.localPlayerController; if ((Object)(object)localPlayerController == (Object)null) { return; } ((Behaviour)nightVisionLight).enabled = false; ((Renderer)greenFlashRenderer).forceRenderingOff = true; ((Renderer)fogShaderPlaneRenderer).forceRenderingOff = true; ViewPerspective.Restore(ref currentPlayerModelState); if (currentPlayer != localPlayerController) { ViewPerspective.Restore(ref localPlayerModelState); } Renderer[] array = currentRenderersToHide; foreach (Renderer val in array) { if (!((Object)(object)val == (Object)null)) { val.forceRenderingOff = false; } } Material obj = currentObstructingMaterial; if (obj != null) { obj.SetFloat(CullModeProperty, currentObstructingMaterialCullMode); } Light sunDirect = TimeOfDay.Instance.sunDirect; if ((Object)(object)sunDirect != (Object)null) { Light sunIndirect = TimeOfDay.Instance.sunIndirect; ((Behaviour)sunDirect).enabled = originalDirectSunlightEnabled; ((Behaviour)sunIndirect).enabled = originalIndirectSunlightEnabled; } Volume blackSkyVolume = StartOfRound.Instance.blackSkyVolume; blackSkyVolume.weight = originalBlackSkyVolumeWeight; if ((Object)(object)sunRootTransform != (Object)null) { sunRootTransform.localScale = originalSunRootScale; } SetMatchLocalPlayerPositions(((Component)localPlayerController).transform.position); SetTargetWeathersVisible(visible: false); } private void ApplyRenderingOverrides() { if (!((Object)(object)currentAttachmentPoint == (Object)null)) { HDAdditionalLightData indirectLightData = TimeOfDay.Instance.indirectLightData; if ((Object)(object)indirectLightData != (Object)null) { originalIndirectSunlightDimmer = indirectLightData.lightDimmer; indirectLightData.lightDimmer = targetIndirectSunlightDimmer; targetIndirectSunlightDimmer = indirectLightData.lightDimmer; } SetTargetWeathersVisible(visible: true); } } private void RevertRenderingOverrides() { if (!((Object)(object)currentAttachmentPoint == (Object)null)) { HDAdditionalLightData indirectLightData = TimeOfDay.Instance.indirectLightData; if ((Object)(object)indirectLightData != (Object)null) { indirectLightData.lightDimmer = originalIndirectSunlightDimmer; } SetTargetWeathersVisible(visible: false); } } private void UpdateTargetStatusDuringUpdate() { if (targetDirtyStatus.HasFlag(TargetDirtyStatus.Immediate)) { UpdateTargetStatus(); } } private void UpdateOverrides(float deltaTime) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)currentActualTarget == (Object)null) { return; } TargetTracker.TargetInfo currentInfo = TargetTracker.GetCurrentInfo(currentActualTarget); bool flag = PositionIsInInterior(CameraTransform.position); bool flag2 = false; if ((Object)(object)currentInfo?.lastTrigger != (Object)null) { flag2 = currentInfo.lastTrigger.insideLighting; } targetSunlightEnabled = !flag; targetBlackSkyVolumeWeight = (flag ? 1 : 0); targetIndirectSunlightDimmer = Mathf.Lerp(targetIndirectSunlightDimmer, (float)((!flag2) ? 1 : 0), Mathf.Clamp01(5f * deltaTime)); for (int i = 0; i < targetWeatherComponents.Length; i++) { WeatherEffectComponents weatherEffectComponents = targetWeatherComponents[i]; if (weatherEffectComponents != null) { if (flag) { weatherEffectComponents.enabled = false; } else if (currentInfo != null && i < currentInfo.enabledWeathers.Length) { weatherEffectComponents.enabled = currentInfo.enabledWeathers[i]; } else { weatherEffectComponents.enabled = false; } weatherEffectComponents.Update(currentActualTarget, flag, deltaTime); } } } private void LateUpdate() { //IL_0119: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Camera == (Object)null) { return; } UpdateTargetStatusDuringUpdate(); PlayerControllerB val = StartOfRound.Instance.localPlayerController; if ((Object)(object)val == (Object)null) { return; } if ((Object)(object)val.spectatedPlayerScript != (Object)null) { val = val.spectatedPlayerScript; } UpdateOverrides(Time.deltaTime); bool flag = keepCameraOn || ((Object)(object)MonitorRenderer != (Object)null && MonitorRenderer.isVisible && val.isInHangarShipRoom && IsScreenPowered()); CameraRenderingStatus cameraRenderingStatus = CameraRenderingStatus.Culled; if (flag) { cameraRenderingStatus = GetUpdatedCameraStatus(); if (cameraRenderingStatus == CameraRenderingStatus.TargetDisabledOnShip && (!disableCameraWhileTargetIsOnShip || keepCameraOn)) { cameraRenderingStatus = CameraRenderingStatus.Rendering; } flag = !IsBlanked; } SetStatus(cameraRenderingStatus); if (!flag) { ((Behaviour)Camera).enabled = false; return; } if (radarBoosterPanSpeed != 0f) { panAngle = (panAngle + Time.deltaTime * radarBoosterPanSpeed) % 360f; } else { panAngle = 270f; } if (panCamera) { CameraTransform.localRotation = Quaternion.Euler(0f, panAngle, 0f); } if (timePerFrame > 0f) { elapsedSinceLastFrame += Time.deltaTime; ((Behaviour)Camera).enabled = elapsedSinceLastFrame >= timePerFrame; elapsedSinceLastFrame %= timePerFrame; } else { ((Behaviour)Camera).enabled = true; } } private void OnDisable() { SetStatus(CameraRenderingStatus.Disabled); UpdateScreenMaterial(); if ((Object)(object)Camera != (Object)null) { ((Behaviour)Camera).enabled = false; } } private void OnEnable() { UpdateScreenMaterial(); } private void OnDestroy() { if ((Object)(object)CameraContainer != (Object)null) { Object.Destroy((Object)(object)((Component)CameraContainer).gameObject); } AllBodyCams = AllBodyCams.Where((BodyCamComponent bodyCam) => bodyCam != this).ToArray(); DestroyTargetWeatherEffects(); SyncBodyCamToRadarMap.OnBodyCamDestroyed(this); BodyCam.BodyCamDestroyed(this); } private static bool PlayerContainsRenderer(PlayerControllerB player, Renderer renderer) { if ((Object)(object)player == (Object)null) { return false; } if ((Object)(object)player.thisPlayerModelArms == (Object)(object)renderer) { return true; } if ((Object)(object)player.thisPlayerModel == (Object)(object)renderer) { return true; } return false; } public bool HasReference(Renderer renderer) { if (targetDirtyStatus.HasFlag(TargetDirtyStatus.UntilRender)) { return false; } if (targetDirtyStatus.HasFlag(TargetDirtyStatus.Immediate)) { UpdateTargetStatus(); } if (PlayerContainsRenderer(currentPlayer, renderer)) { return true; } if (PlayerContainsRenderer(StartOfRound.Instance?.localPlayerController, renderer)) { return true; } if (Array.IndexOf(currentRenderersToHide, renderer) != -1) { return true; } return false; } public bool HasReference(GameObject gameObject) { if (targetDirtyStatus.HasFlag(TargetDirtyStatus.UntilRender)) { return false; } if (targetDirtyStatus.HasFlag(TargetDirtyStatus.Immediate)) { UpdateTargetStatus(); } if (currentPlayerModelState.ReferencesObject(gameObject)) { return true; } if (localPlayerModelState.ReferencesObject(gameObject)) { return true; } return false; } public static bool AnyBodyCamHasReference(Renderer renderer) { BodyCamComponent[] allBodyCams = AllBodyCams; foreach (BodyCamComponent bodyCamComponent in allBodyCams) { if (bodyCamComponent.HasReference(renderer)) { return true; } } return false; } public static bool AnyBodyCamHasReference(GameObject gameObject) { BodyCamComponent[] allBodyCams = AllBodyCams; foreach (BodyCamComponent bodyCamComponent in allBodyCams) { if (bodyCamComponent.HasReference(gameObject)) { return true; } } return false; } } public enum CameraRenderingStatus { Rendering, Disabled, TargetInvalid, TargetDisabledOnShip, Culled } public enum CameraModeOptions { Body, Head } public enum BoolWithDefault { False, True, Default } [BepInPlugin("Sygnano.OpenBodyCams-V81", "OpenBodyCams-V81", "3.0.11")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string MOD_NAME = "OpenBodyCams-V81"; public const string MOD_UNIQUE_NAME = "Sygnano.OpenBodyCams-V81"; public const string MOD_VERSION = "3.0.11"; private readonly Harmony harmony = new Harmony("Sygnano.OpenBodyCams-V81"); public static ConfigEntry CameraMode; public static ConfigEntry HorizontalResolution; public static ConfigEntry FieldOfView; public static ConfigEntry RenderDistance; public static ConfigEntry Framerate; public const float NightVisionIntensityBase = 367f; public const float NightVisionRangeBase = 12f; public static ConfigEntry NightVisionBrightness; public static ConfigEntry MonitorEmissiveColor; public static ConfigEntry MonitorTextureFiltering; public static ConfigEntry RadarBoosterPanRPM; public static ConfigEntry UseTargetTransitionAnimation; public static ConfigEntry DisableCameraWhileTargetIsOnShip; public static ConfigEntry EnableCamera; public static ConfigEntry DisplayOriginalScreenWhenDisabled; public static ConfigEntry OverlayEnabled; public static ConfigEntry OverlayTextScale; public static ConfigEntry DefaultText; public static ConfigEntry BuyAntennaText; public static ConfigEntry AntennaStoredText; public static ConfigEntry TargetInvalidText; public static ConfigEntry TargetOnShipText; public static ConfigEntry TerminalPiPBodyCamEnabled; public static ConfigEntry TerminalPiPPosition; public static ConfigEntry TerminalPiPWidth; public static ConfigEntry ShipUpgradeEnabled; public static ConfigEntry ShipUpgradePrice; public static ConfigEntry GeneralImprovementsBetterMonitorIndex; public static ConfigEntry EnableMoreCompanyCosmeticsCompatibility; public static ConfigEntry EnableAdvancedCompanyCosmeticsCompatibility; public static ConfigEntry EnableModelReplacementAPICompatibility; public static ConfigEntry EnableLethalVRMCompatibility; public static ConfigEntry EnableReservedItemSlotsCompatibility; public static ConfigEntry SwapInternalAndExternalShipCameras; public static ConfigEntry DisableCameraOnSmallMonitor; public static ConfigEntry ExternalCameraEmissiveColor; public static ConfigEntry FixDroppedItemRotation; public static ConfigEntry FixMaskedConversionForClients; public static ConfigEntry DisplayWeatherBasedOnPerspective; public static ConfigEntry PrintCosmeticsDebugInfo; public static ConfigEntry ReferencedObjectDestructionDetectionEnabled; public static ConfigEntry LastConfigVersion; private static readonly Harmony DestructionDetectionPatch = new Harmony("Sygnano.OpenBodyCams-V81.DestructionDetectionPatch"); internal static AssetBundle Assets; private const string OptionDisabledWithBetterMonitors = "This has no effect when GeneralImprovements's UseBetterMonitors option is enabled."; public static Plugin Instance { get; private set; } public ManualLogSource Logger => ((BaseUnityPlugin)this).Logger; private void Awake() { //IL_073b: Unknown result type (might be due to invalid IL or missing references) //IL_0745: Expected O, but got Unknown Instance = this; string text = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "openbodycams"); Assets = AssetBundle.LoadFromFile(text); if ((Object)(object)Assets != (Object)null) { Instance.Logger.LogInfo((object)"Successfully loaded OpenBodyCams assets."); } else { Instance.Logger.LogError((object)"Failed to load the asset bundle, some features may be missing."); } CameraMode = ((BaseUnityPlugin)this).Config.Bind("Camera", "Mode", CameraModeOptions.Head, "Choose where to attach the camera. 'Head' will attach the camera to the right side of the head, 'Body' will attach it to the chest."); HorizontalResolution = ((BaseUnityPlugin)this).Config.Bind("Camera", "HorizontalResolution", 160, "The horizontal resolution of the rendering. The vertical resolution is calculated based on the aspect ratio of the monitor."); FieldOfView = ((BaseUnityPlugin)this).Config.Bind("Camera", "FieldOfView", 65f, "The vertical FOV of the camera in degrees."); RenderDistance = ((BaseUnityPlugin)this).Config.Bind("Camera", "RenderDistance", 25f, "The far clip plane for the body cam. Lowering may improve framerates."); Framerate = ((BaseUnityPlugin)this).Config.Bind("Camera", "Framerate", 0f, "The number of frames to render per second. A value of 0 will render at the game's framerate. Setting this significantly below the average framerate on the ship will improve performance."); NightVisionBrightness = ((BaseUnityPlugin)this).Config.Bind("Camera", "NightVisionBrightness", 1f, "A multiplier for the intensity of the area light used to brighten dark areas. A value of 1 is identical to the player's actual vision."); MonitorEmissiveColor = ((BaseUnityPlugin)this).Config.Bind("Camera", "MonitorEmissiveColor", "0.05, 0.13, 0.05", "Adjust the color that is emitted from the body cam monitor, using comma-separated decimal numbers for red, green and blue."); MonitorTextureFiltering = ((BaseUnityPlugin)this).Config.Bind("Camera", "MonitorTextureFiltering", (FilterMode)1, "The texture filtering to use for the body cam on the monitor. Bilinear and Trilinear will result in a smooth image, while Point will result in sharp square edges. If Point is used, a fairly high resolution is recommended."); RadarBoosterPanRPM = ((BaseUnityPlugin)this).Config.Bind("Camera", "RadarBoosterPanRPM", 9f, "The rotations per minute to turn the camera when a radar booster is selected. If the value is set to 0, the radar booster camera will face in the direction player faces when it is placed."); UseTargetTransitionAnimation = ((BaseUnityPlugin)this).Config.Bind("Camera", "UseTargetTransitionAnimation", true, "Enables a green flash animation on the body cam screen mirroring the one that the radar map shows when switching targets."); DisableCameraWhileTargetIsOnShip = ((BaseUnityPlugin)this).Config.Bind("Camera", "DisableCameraWhileTargetIsOnShip", false, "With this option enabled, the camera will stop rendering when the target is onboard the ship to reduce the performance hit of rendering a large number of items on the ship twice."); EnableCamera = ((BaseUnityPlugin)this).Config.Bind("Camera", "EnableCamera", true, "Enables/disables rendering of the body cam, and can be enabled/disabled during a game with LethalConfig."); DisplayOriginalScreenWhenDisabled = ((BaseUnityPlugin)this).Config.Bind("Camera", "DisplayOriginalScreenWhenDisabled", true, "When enabled, the screen that the body cam replaces will be displayed when it is disabled due to invalid targets."); CameraMode.SettingChanged += delegate { BodyCamComponent.MarkTargetStatusChangedForAllBodyCams(); }; FieldOfView.SettingChanged += delegate { BodyCamComponent.UpdateAllCameraSettings(); }; RenderDistance.SettingChanged += delegate { BodyCamComponent.UpdateAllCameraSettings(); }; NightVisionBrightness.SettingChanged += delegate { BodyCamComponent.UpdateAllCameraSettings(); }; MonitorTextureFiltering.SettingChanged += delegate { BodyCamComponent.UpdateAllCameraSettings(); }; RadarBoosterPanRPM.SettingChanged += delegate { BodyCamComponent.UpdateAllCameraSettings(); }; DisableCameraWhileTargetIsOnShip.SettingChanged += delegate { BodyCamComponent.UpdateAllCameraSettings(); }; DisplayOriginalScreenWhenDisabled.SettingChanged += delegate { ShipObjects.UpdateMainBodyCamNoTargetMaterial(); }; HorizontalResolution.SettingChanged += delegate { ShipObjects.UpdateMainBodyCamSettings(); }; Framerate.SettingChanged += delegate { ShipObjects.UpdateMainBodyCamSettings(); }; MonitorEmissiveColor.SettingChanged += delegate { ShipObjects.UpdateMainBodyCamSettings(); }; EnableCamera.SettingChanged += delegate { ShipObjects.UpdateMainBodyCamSettings(); }; OverlayEnabled = ((BaseUnityPlugin)this).Config.Bind("Overlay", "Enabled", true, "Displays an overlay on the monitor that the body cam replaces to communicate the status of the body cam. This will only work if the screen is displaying a render texture connected to a camera. Restart the lobby to apply."); OverlayTextScale = ((BaseUnityPlugin)this).Config.Bind("Overlay", "TextScale", 1f, "The factor by which to scale the text on the overlay screen."); DefaultText = ((BaseUnityPlugin)this).Config.Bind("Overlay", "DefaultText", "", "The text displayed on the body cam monitor when it is operating normally."); BuyAntennaText = ((BaseUnityPlugin)this).Config.Bind("Overlay", "BuyAntennaText", "Body cam ${price}", "The text displayed on the body cam monitor to prompt players to buy the antenna in the store to enable body cams."); AntennaStoredText = ((BaseUnityPlugin)this).Config.Bind("Overlay", "AntennaStoredText", "Antenna stored", "The text displayed when the antenna is stored, preventing the body cams displaying on the monitor."); TargetInvalidText = ((BaseUnityPlugin)this).Config.Bind("Overlay", "TargetInvalidText", "Signal lost", "The text displayed when the selected target is invalid (for example, the target is a player that has been eaten)."); TargetOnShipText = ((BaseUnityPlugin)this).Config.Bind("Overlay", "TargetOnShipText", "Target on ship", "The text displayed when the selected target is safe on the ship with DisableCameraWhileTargetIsOnShip enabled."); OverlayTextScale.SettingChanged += UpdateOverlayPrefs; DefaultText.SettingChanged += UpdateOverlayText; BuyAntennaText.SettingChanged += UpdateOverlayText; AntennaStoredText.SettingChanged += UpdateOverlayText; TargetInvalidText.SettingChanged += UpdateOverlayText; TargetOnShipText.SettingChanged += UpdateOverlayText; TerminalPiPBodyCamEnabled = ((BaseUnityPlugin)this).Config.Bind("Terminal", "EnablePiPBodyCam", false, "Adds a 'view bodycam' command to the terminal that places a picture-in-picture view of the bodycam in front of the radar map."); TerminalPiPPosition = ((BaseUnityPlugin)this).Config.Bind("Terminal", "PiPPosition", PiPPosition.BottomRight, "The corner inside the terminal's radar map to align the body cam to."); TerminalPiPWidth = ((BaseUnityPlugin)this).Config.Bind("Terminal", "PiPWidth", 150, "The width of the picture-in-picture in pixels."); TerminalPiPBodyCamEnabled.SettingChanged += delegate { TerminalCommands.Initialize(); }; TerminalPiPPosition.SettingChanged += delegate { TerminalCommands.Initialize(); }; TerminalPiPWidth.SettingChanged += delegate { TerminalCommands.Initialize(); }; harmony.PatchAll(typeof(TerminalCommands)); ShipUpgradeEnabled = ((BaseUnityPlugin)this).Config.Bind("ShipUpgrade", "Enabled", true, "Adds a ship upgrade that enables the body cam on the main monitors only after it is bought.\n\nNOTE: The upgrade will only be available if LethalLib is installed. Without it, the main body cam will always be enabled."); ShipUpgradePrice = ((BaseUnityPlugin)this).Config.Bind("ShipUpgrade", "Price", 200, "The price at which the ship upgrade is sold in the store."); GeneralImprovementsBetterMonitorIndex = ((BaseUnityPlugin)this).Config.Bind("Compatibility", "GeneralImprovementsBetterMonitorIndex", 0, new ConfigDescription("With GeneralImprovements's UseBetterMonitors enabled, choose which monitor to display the body cam on.\nA value of 0 will place it on the large monitor on the right.\nValues greater than 0 go left to right, top to bottom, skipping the large center monitor. Without AddMoreBetterMonitors, the maximum value is 9, rather than 14.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 14), Array.Empty())); EnableMoreCompanyCosmeticsCompatibility = ((BaseUnityPlugin)this).Config.Bind("Compatibility", "EnableMoreCompanyCosmeticsCompatibility", true, "If this is enabled, a patch will be applied to MoreCompany to spawn cosmetics for the local player, and all cosmetics will be shown and hidden based on the camera's perspective."); EnableAdvancedCompanyCosmeticsCompatibility = ((BaseUnityPlugin)this).Config.Bind("Compatibility", "EnableAdvancedCompanyCosmeticsCompatibility", true, "When this is enabled and AdvancedCompany is installed, all cosmetics will be shown and hidden based on the camera's perspective."); EnableModelReplacementAPICompatibility = ((BaseUnityPlugin)this).Config.Bind("Compatibility", "EnableModelReplacementAPICompatibility", true, "When enabled, this will get the third person model replacement and hide/show it based on the camera's perspective."); EnableLethalVRMCompatibility = ((BaseUnityPlugin)this).Config.Bind("Compatibility", "EnableLethalVRMCompatibility", true, "When enabled, any VRM model will be hidden/shown based on the camera's perspective."); EnableReservedItemSlotsCompatibility = ((BaseUnityPlugin)this).Config.Bind("Compatibility", "EnableReservedItemSlotsCompatibility", true, "When enabled, items holstered in reserved item slots will be hidden/shown based on the perspective."); SwapInternalAndExternalShipCameras = ((BaseUnityPlugin)this).Config.Bind("Ship", "SwapInternalAndExternalShipCameras", false, "Causes the internal ship camera to be placed onto big monitor, and the external one to be placed onto the small monitor. This has no effect when GeneralImprovements's UseBetterMonitors option is enabled."); DisableCameraOnSmallMonitor = ((BaseUnityPlugin)this).Config.Bind("Ship", "DisableCameraOnSmallMonitor", false, "Disables whichever camera is placed onto the small camera monitor. This has no effect when GeneralImprovements's UseBetterMonitors option is enabled."); ExternalCameraEmissiveColor = ((BaseUnityPlugin)this).Config.Bind("Ship", "ExternalCameraEmissiveColor", "", "Sets the color emitted by the external camera screen, using comma-separated decimal numbers for red, green and blue."); ExternalCameraEmissiveColor.SettingChanged += delegate { ShipObjects.SetExternalCameraEmissiveColor(); }; FixDroppedItemRotation = ((BaseUnityPlugin)this).Config.Bind("Misc", "FixDroppedItemRotation", true, "If enabled, the mod will patch a bug that causes the rotation of dropped items to be desynced between clients."); FixMaskedConversionForClients = ((BaseUnityPlugin)this).Config.Bind("Misc", "FixMaskedConversionForClients", true, "If enabled, the mod will patch a bug that causes maps and body cams to be unable to target a player that was converted into a masked enemy."); DisplayWeatherBasedOnPerspective = ((BaseUnityPlugin)this).Config.Bind("Experimental", "DisplayWeatherBasedOnPerspective", BoolWithDefault.Default, "If enabled, a clone of each weather effect will be simulated on the body cam target. This allows rain and fog effects to be visible on body cams when far from the viewer. This may cause issues with some modded weathers.\n\nThe Default value will leave the feature disabled, but may be changed in future versions."); DisplayWeatherBasedOnPerspective.SettingChanged += delegate { BodyCamComponent.CreateTargetWeatherEffectsForAllCams(); }; PrintCosmeticsDebugInfo = ((BaseUnityPlugin)this).Config.Bind("Debug", "PrintCosmeticsDebugInfo", false, "Prints extra information about the cosmetics being collected for each player, as well as the code that is causing the collection."); ReferencedObjectDestructionDetectionEnabled = ((BaseUnityPlugin)this).Config.Bind("Debug", "ModelDestructionDebuggingPatchEnabled", false, "Enable this option when reproducing a camera freeze. This will cause a debug message to be printed when a model that a body cam is tracking is destroyed."); LastConfigVersion = ((BaseUnityPlugin)this).Config.Bind("Debug", "LastConfigVersion", "", "The last version of the mod that loaded/saved this config file. Used for setting migration."); PrintCosmeticsDebugInfo.SettingChanged += delegate { Cosmetics.PrintDebugInfo = PrintCosmeticsDebugInfo.Value; }; Cosmetics.PrintDebugInfo = PrintCosmeticsDebugInfo.Value; ReferencedObjectDestructionDetectionEnabled.SettingChanged += delegate { UpdateReferencedObjectDestructionDetectionEnabled(); }; UpdateReferencedObjectDestructionDetectionEnabled(); MigrateSettings(); harmony.PatchAll(typeof(PatchTerminal)); harmony.PatchAll(typeof(PatchStartOfRound)); harmony.PatchAll(typeof(PatchManualCameraRenderer)); harmony.PatchAll(typeof(PatchPlayerControllerB)); harmony.PatchAll(typeof(PatchHauntedMaskItem)); harmony.PatchAll(typeof(PatchMaskedPlayerEnemy)); harmony.PatchAll(typeof(PatchUnlockableSuit)); harmony.PatchAll(typeof(PatchCentipedeAI)); harmony.PatchAll(typeof(PatchFlowerSnakeEnemy)); harmony.PatchAll(typeof(PatchHDRenderPipeline)); harmony.PatchAll(typeof(PatchRadarBoosterItem)); harmony.PatchAll(typeof(PatchDeadBodyInfo)); harmony.PatchAll(typeof(PatchTimeOfDay)); harmony.PatchAll(typeof(PatchFixItemDropping)); BodyCamComponent.InitializeStatic(); SetUpCameraCallbacks(); ShipUpgrades.Initialize(); Cosmetics.Initialize(harmony); Application.SetStackTraceLogType((LogType)3, (StackTraceLogType)0); Application.SetStackTraceLogType((LogType)2, (StackTraceLogType)0); Application.SetStackTraceLogType((LogType)0, (StackTraceLogType)0); Application.SetStackTraceLogType((LogType)1, (StackTraceLogType)0); static void UpdateOverlayPrefs(object target, EventArgs args) { if ((Object)(object)ShipObjects.Overlay != (Object)null) { ShipObjects.Overlay.UpdatePreferences(); } } static void UpdateOverlayText(object target, EventArgs args) { if ((Object)(object)ShipObjects.Overlay != (Object)null) { ShipObjects.Overlay.UpdateText(); } } } private void UpdateReferencedObjectDestructionDetectionEnabled() { if (ReferencedObjectDestructionDetectionEnabled.Value) { DestructionDetectionPatch.PatchAll(typeof(PatchModelDestructionDebugging)); } else { DestructionDetectionPatch.UnpatchSelf(); } } private void MigrateSettings() { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Expected O, but got Unknown //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Expected O, but got Unknown Dictionary orphanedEntries; try { orphanedEntries = ((BaseUnityPlugin)this).Config.OrphanedEntries; } catch (MissingFieldException) { Logger.LogError((object)"Failed to migrate config, orphaned entries property was not found."); return; } if (!Version.TryParse(LastConfigVersion.Value, out Version result)) { result = new Version(2, 0, 0); } Logger.LogInfo((object)$"Last config version is {result}."); ConfigDefinition val = new ConfigDefinition("Misc", "DisableInternalShipCamera"); if (orphanedEntries.TryGetValue(val, out var value)) { Logger.LogInfo((object)$"{val} option was found set to '{value}' in the config, migrating it over to {((ConfigEntryBase)DisableCameraOnSmallMonitor).Definition}."); orphanedEntries.Remove(val); DisableCameraOnSmallMonitor.Value = TomlTypeConverter.ConvertToValue(value); } if (result < new Version(2, 0, 2) && !ShipUpgradeEnabled.Value) { Logger.LogInfo((object)$"{((ConfigEntryBase)ShipUpgradeEnabled).Definition} was set to its 2.0.0 default value 'false', resetting it to 'true'."); ShipUpgradeEnabled.Value = true; } if (result < new Version(3, 0, 0)) { orphanedEntries.Remove(new ConfigDefinition("Debug", "BruteForcePreventFreezes")); } LastConfigVersion.Value = "3.0.11"; } private static Color ParseColor(string str) { //IL_007c: Unknown result type (might be due to invalid IL or missing references) float[] array = (from x in str.Split(new char[2] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries) select float.Parse(x.Trim(), CultureInfo.InvariantCulture)).ToArray(); if (array.Length < 3) { throw new FormatException("Not enough color components"); } if (array.Length > 4) { throw new FormatException("Too many color components"); } return new Color(array[0], array[1], array[2], (array.Length == 4) ? array[3] : 0f); } internal static Color GetBodyCamEmissiveColor() { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) try { return ParseColor(MonitorEmissiveColor.Value); } catch (Exception arg) { Instance.Logger.LogWarning((object)$"Failed to parse the body cam screen's emissive color: {arg}"); return ParseColor((string)((ConfigEntryBase)MonitorEmissiveColor).DefaultValue); } } internal static Color? GetExternalCameraEmissiveColor() { //IL_002d: Unknown result type (might be due to invalid IL or missing references) string value = ExternalCameraEmissiveColor.Value; if (value == "") { return null; } try { return ParseColor(ExternalCameraEmissiveColor.Value); } catch (Exception arg) { Instance.Logger.LogWarning((object)$"Failed to parse the external camera screen's emissive color: {arg}"); return null; } } private void SetUpCameraCallbacks() { PatchHDRenderPipeline.BeforeCameraCulling = (Action)Delegate.Combine(PatchHDRenderPipeline.BeforeCameraCulling, new Action(BeforeCullingAnyCamera)); PatchHDRenderPipeline.BeforeCameraRendering = (Action)Delegate.Combine(PatchHDRenderPipeline.BeforeCameraRendering, new Action(BeforeRenderingAnyCamera)); RenderPipelineManager.endCameraRendering += AfterRenderingAnyCamera; } private void BeforeCullingAnyCamera(ScriptableRenderContext context, Camera camera) { BodyCamComponent.BeforeCullingAnyCamera(camera); } private void BeforeRenderingAnyCamera(ScriptableRenderContext context, Camera camera) { BodyCamComponent.BeforeRenderingAnyCamera(camera); OverlayManager.BeforeRenderingAnyCamera(camera); } private void AfterRenderingAnyCamera(ScriptableRenderContext context, Camera camera) { BodyCamComponent.AfterRenderingAnyCamera(camera); OverlayManager.AfterRenderingAnyCamera(camera); } } public static class ShipObjects { internal static Material BlackScreenMaterial; internal static Terminal TerminalScript; internal static bool TwoRadarCamsPresent; internal static BodyCamComponent MainBodyCam; internal static OverlayManager Overlay; internal static ManualCameraRenderer InternalCameraRenderer; internal static ManualCameraRenderer ExternalCameraRenderer; internal static Material ExternalCameraMaterial; internal static Color OriginalExternalCameraEmissiveColor; internal static MeshRenderer DoorScreenRenderer; internal static bool DoorScreenUsesExternalCamera; internal static ManualCameraRenderer ShipCameraOnSmallMonitor; internal static ManualCameraRenderer CameraReplacedByBodyCam; public static void EarlyInitialization() { //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) if (HasFinishedEarlyInitialization()) { return; } BlackScreenMaterial = StartOfRound.Instance.mapScreen.offScreenMat; GameObject obj = GameObject.Find("Environment/HangarShip/Cameras/ShipCamera"); InternalCameraRenderer = ((obj != null) ? obj.GetComponent() : null); GameObject obj2 = GameObject.Find("Environment/HangarShip/Cameras/FrontDoorSecurityCam/SecurityCamera"); ExternalCameraRenderer = ((obj2 != null) ? obj2.GetComponent() : null); GameObject obj3 = GameObject.Find("Environment/HangarShip/ShipModels2b/MonitorWall/SingleScreen"); DoorScreenRenderer = ((obj3 != null) ? obj3.GetComponent() : null); ShipCameraOnSmallMonitor = InternalCameraRenderer; BodyCamComponent.InitializeAtStartOfGame(); if ((Object)(object)ExternalCameraRenderer != (Object)null) { int cameraMaterialIndex = GetCameraMaterialIndex(ExternalCameraRenderer); if (cameraMaterialIndex != -1) { ExternalCameraMaterial = ((Renderer)ExternalCameraRenderer.mesh).sharedMaterials[cameraMaterialIndex]; OriginalExternalCameraEmissiveColor = ExternalCameraMaterial.GetColor("_EmissiveColor"); SetExternalCameraEmissiveColor(); } } } private static bool HasFinishedEarlyInitialization() { return (Object)(object)ShipCameraOnSmallMonitor != (Object)null; } internal static void SetExternalCameraEmissiveColor() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) Color valueOrDefault = Plugin.GetExternalCameraEmissiveColor().GetValueOrDefault(OriginalExternalCameraEmissiveColor); Material externalCameraMaterial = ExternalCameraMaterial; if (externalCameraMaterial != null) { externalCameraMaterial.SetColor("_EmissiveColor", valueOrDefault); } } public static void LateInitialization() { ManageShipCameras(); TwoRadarCamsPresent = (Object)(object)((Component)TerminalScript).GetComponent() != (Object)null; if ((Object)(object)DoorScreenRenderer != (Object)null && (Object)(object)ExternalCameraRenderer?.cam != (Object)null) { DoorScreenUsesExternalCamera = ((Renderer)DoorScreenRenderer).sharedMaterials.Any((Material mat) => (Object)(object)mat.mainTexture == (Object)(object)ExternalCameraRenderer.cam.targetTexture); } InitializeBodyCam(); TerminalCommands.Initialize(); if (!TwoRadarCamsPresent && ((NetworkBehaviour)StartOfRound.Instance).IsServer) { ManualCameraRenderer mapScreen = StartOfRound.Instance.mapScreen; mapScreen.SwitchRadarTargetAndSync(Math.Min(mapScreen.targetTransformIndex, mapScreen.radarTargets.Count - 1)); } } private static void ManageShipCameras() { if (!GeneralImprovementsCompatibility.BetterMonitorsEnabled) { if (Plugin.SwapInternalAndExternalShipCameras.Value) { SwapShipCameras(); } if (Plugin.DisableCameraOnSmallMonitor.Value) { DisableCameraOnSmallMonitor(); } } } private static int GetCameraMaterialIndex(ManualCameraRenderer shipCamera) { if ((Object)(object)shipCamera == (Object)null) { return -1; } if ((Object)(object)shipCamera.mesh == (Object)null) { return -1; } Camera val = shipCamera.cam; if ((Object)(object)val == (Object)null) { val = ((Component)shipCamera).GetComponent(); } RenderTexture texture = val.targetTexture; return Array.FindIndex(((Renderer)shipCamera.mesh).sharedMaterials, (Material material) => (Object)(object)material.mainTexture == (Object)(object)texture); } private static void SwapShipCameras() { int cameraMaterialIndex = GetCameraMaterialIndex(InternalCameraRenderer); int cameraMaterialIndex2 = GetCameraMaterialIndex(ExternalCameraRenderer); if (cameraMaterialIndex == -1 || cameraMaterialIndex2 == -1) { Plugin.Instance.Logger.LogError((object)$"{((ConfigEntryBase)Plugin.SwapInternalAndExternalShipCameras).Definition} is enabled, but one of the ship's cameras' materials was not found."); return; } Material material = ((Renderer)InternalCameraRenderer.mesh).sharedMaterials[cameraMaterialIndex]; ((Renderer)(object)InternalCameraRenderer.mesh).SetMaterial(cameraMaterialIndex, ((Renderer)ExternalCameraRenderer.mesh).sharedMaterials[cameraMaterialIndex2]); ((Renderer)(object)ExternalCameraRenderer.mesh).SetMaterial(cameraMaterialIndex2, material); ManualCameraRenderer internalCameraRenderer = InternalCameraRenderer; ManualCameraRenderer externalCameraRenderer = ExternalCameraRenderer; MeshRenderer mesh = ExternalCameraRenderer.mesh; MeshRenderer mesh2 = InternalCameraRenderer.mesh; internalCameraRenderer.mesh = mesh; externalCameraRenderer.mesh = mesh2; ShipCameraOnSmallMonitor = ExternalCameraRenderer; } private static void DisableCameraOnSmallMonitor() { int cameraMaterialIndex = GetCameraMaterialIndex(ShipCameraOnSmallMonitor); if (cameraMaterialIndex == -1) { Plugin.Instance.Logger.LogError((object)$"{((ConfigEntryBase)Plugin.DisableCameraOnSmallMonitor).Definition} is enabled, but the small monitor's camera material was not found."); return; } ((Renderer)(object)ShipCameraOnSmallMonitor.mesh).SetMaterial(cameraMaterialIndex, BlackScreenMaterial); ((Behaviour)ShipCameraOnSmallMonitor.cam).enabled = false; ((Behaviour)ShipCameraOnSmallMonitor).enabled = false; } private static void InitializeBodyCam() { GameObject val = GameObject.Find("Environment/HangarShip/ShipModels2b/MonitorWall/Cube.001"); if ((Object)(object)val == (Object)null) { Plugin.Instance.Logger.LogError((object)"Could not find the bottom monitors' game object."); return; } if ((Object)(object)val.GetComponent() == (Object)null) { MainBodyCam = val.AddComponent(); val.AddComponent(); if (!GeneralImprovementsCompatibility.BetterMonitorsEnabled) { MainBodyCam.MonitorRenderer = (Renderer)(object)val.GetComponent(); MainBodyCam.MonitorMaterialIndex = 2; MainBodyCam.MonitorDisabledMaterial = MainBodyCam.MonitorRenderer.sharedMaterials[MainBodyCam.MonitorMaterialIndex]; } else { int id = Plugin.GeneralImprovementsBetterMonitorIndex.Value - 1; GeneralImprovementsCompatibility.GeneralImprovementsMonitorSpecification? monitorForID = GeneralImprovementsCompatibility.GetMonitorForID(id); if (monitorForID.HasValue) { MainBodyCam.MonitorRenderer = monitorForID.Value.Renderer; MainBodyCam.MonitorMaterialIndex = monitorForID.Value.MaterialIndex; MainBodyCam.MonitorDisabledMaterial = monitorForID.Value.OriginalMaterial; } } if ((Object)(object)MainBodyCam.MonitorRenderer == (Object)null) { Plugin.Instance.Logger.LogError((object)"Failed to find the monitor renderer."); Object.DestroyImmediate((Object)(object)MainBodyCam); return; } if ((Object)(object)MainBodyCam.MonitorDisabledMaterial == (Object)null) { MainBodyCam.MonitorDisabledMaterial = BlackScreenMaterial; } UpdateMainBodyCamNoTargetMaterial(); if (ShipUpgrades.BodyCamUnlockable != null) { ((Behaviour)MainBodyCam).enabled = ShipUpgrades.BodyCamUnlockableIsPlaced; } else { BodyCam.BodyCamReceiverBecameEnabled(); } CameraReplacedByBodyCam = null; Texture mainTexture = MainBodyCam.MonitorDisabledMaterial.mainTexture; RenderTexture val2 = (RenderTexture)(object)((mainTexture is RenderTexture) ? mainTexture : null); if (val2 != null) { ManualCameraRenderer internalCameraRenderer = InternalCameraRenderer; object obj; if (internalCameraRenderer == null) { obj = null; } else { Camera cam = internalCameraRenderer.cam; obj = ((cam != null) ? cam.targetTexture : null); } if ((Object)(object)val2 == (Object)obj) { CameraReplacedByBodyCam = InternalCameraRenderer; } else { ManualCameraRenderer externalCameraRenderer = ExternalCameraRenderer; object obj2; if (externalCameraRenderer == null) { obj2 = null; } else { Camera cam2 = externalCameraRenderer.cam; obj2 = ((cam2 != null) ? cam2.targetTexture : null); } if ((Object)(object)val2 == (Object)obj2) { CameraReplacedByBodyCam = ExternalCameraRenderer; } } } } UpdateMainBodyCamSettings(); InitializeMainBodyCamOverlay(); } private static void InitializeMainBodyCamOverlay() { //IL_0060: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)Plugin.Assets == (Object)null) && Plugin.OverlayEnabled.Value) { GameObject val = Object.Instantiate(Plugin.Assets.LoadAsset("Assets/OpenBodyCams/Prefabs/BodyCamOverlayCanvas.prefab")); val.transform.SetParent(GameObject.Find("Systems/UI").transform, false); val.transform.position = new Vector3(0f, 1000f, 0f); Overlay = val.AddComponent(); Overlay.BodyCam = MainBodyCam; } } internal static void UpdateMainBodyCamNoTargetMaterial() { if (Plugin.DisplayOriginalScreenWhenDisabled.Value) { MainBodyCam.MonitorNoTargetMaterial = MainBodyCam.MonitorDisabledMaterial; } else { MainBodyCam.MonitorNoTargetMaterial = null; } MainBodyCam.UpdateScreenMaterial(); } internal static void UpdateMainBodyCamSettings() { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)MainBodyCam == (Object)null)) { MainBodyCam.Resolution = new Vector2Int(Plugin.HorizontalResolution.Value, Plugin.HorizontalResolution.Value * 3 / 4); MainBodyCam.Framerate = Plugin.Framerate.Value; MainBodyCam.EnableCamera = Plugin.EnableCamera.Value; MainBodyCam.UpdateScreenMaterial(); MainBodyCam.MonitorOnMaterial.SetColor("_EmissiveColor", Plugin.GetBodyCamEmissiveColor()); } } } internal static class ShipUpgrades { internal static UnlockableItem BodyCamUnlockable; internal static int BodyCamPrice; internal static bool BodyCamUnlockableIsPlaced; public static void Initialize() { if (!Chainloader.PluginInfos.ContainsKey("evaisa.lethallib")) { Plugin.Instance.Logger.LogInfo((object)"LethalLib is not present, body cam will be enabled by default."); } else { RegisterUnlockables(); } } [MethodImpl(MethodImplOptions.NoInlining)] private static void RegisterUnlockables() { RegisterBodyCamShipUpgrade(); } private static void RegisterBodyCamShipUpgrade() { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Expected O, but got Unknown if (!((Object)(object)Plugin.Assets == (Object)null) && Plugin.ShipUpgradeEnabled.Value) { GameObject val = Plugin.Assets.LoadAsset("Assets/OpenBodyCams/Prefabs/BodyCamAntenna.prefab"); if ((Object)(object)val == (Object)null) { Plugin.Instance.Logger.LogInfo((object)"Body cam antenna prop was not found within the asset bundle."); return; } val.AddComponent(); UnlockableItem val2 = new UnlockableItem { unlockableName = "Bodycam", unlockableType = 1, prefabObject = val, IsPlaceable = true, alwaysInStock = true }; BodyCamPrice = Plugin.ShipUpgradePrice.Value; Unlockables.RegisterUnlockable(val2, BodyCamPrice, (StoreType)1); NetworkPrefabs.RegisterNetworkPrefab(val); Utilities.FixMixerGroups(val); BodyCamUnlockable = val2; Plugin.Instance.Logger.LogInfo((object)$"Registered body cam unlockable for {BodyCamPrice} credits."); } } } internal class EnableMainBodyCam : MonoBehaviour { private void OnEnable() { ShipUpgrades.BodyCamUnlockableIsPlaced = true; BodyCam.BodyCamReceiverBecameEnabled(); if (!((Object)(object)ShipObjects.MainBodyCam == (Object)null)) { ((Behaviour)ShipObjects.MainBodyCam).enabled = true; } } private void OnDisable() { ShipUpgrades.BodyCamUnlockableIsPlaced = false; BodyCam.BodyCamReceiverBecameDisabled(); if (!((Object)(object)ShipObjects.MainBodyCam == (Object)null)) { ((Behaviour)ShipObjects.MainBodyCam).enabled = false; } } } public class SyncBodyCamToRadarMap : MonoBehaviour { private static SyncBodyCamToRadarMap[] AllSynchronizedCams = new SyncBodyCamToRadarMap[0]; internal ManualCameraRenderer MapRenderer; internal BodyCamComponent BodyCam; public static SyncBodyCamToRadarMap[] GetAllSynchronizedCams() { return AllSynchronizedCams; } public ManualCameraRenderer GetMapRenderer() { return MapRenderer; } public BodyCamComponent GetBodyCam() { return BodyCam; } private static void DoForMap(ManualCameraRenderer mapRenderer, Action action) { SyncBodyCamToRadarMap[] allSynchronizedCams = AllSynchronizedCams; foreach (SyncBodyCamToRadarMap syncBodyCamToRadarMap in allSynchronizedCams) { if (syncBodyCamToRadarMap.MapRenderer == mapRenderer) { action(syncBodyCamToRadarMap); } } } public static void UpdateBodyCamTargetForMap(ManualCameraRenderer mapRenderer) { DoForMap(mapRenderer, delegate(SyncBodyCamToRadarMap syncedCam) { syncedCam.UpdateBodyCamTarget(); }); } public static void StartTargetTransitionForMap(ManualCameraRenderer mapRenderer) { DoForMap(mapRenderer, delegate(SyncBodyCamToRadarMap syncedCam) { syncedCam.StartTargetTransition(); }); } private static void DoForCam(BodyCamComponent bodyCam, Action action) { SyncBodyCamToRadarMap[] allSynchronizedCams = AllSynchronizedCams; foreach (SyncBodyCamToRadarMap syncBodyCamToRadarMap in allSynchronizedCams) { if (syncBodyCamToRadarMap.BodyCam == bodyCam) { action(syncBodyCamToRadarMap); } } } public static void UpdateBodyCamTarget(BodyCamComponent bodyCam) { DoForCam(bodyCam, delegate(SyncBodyCamToRadarMap syncedCam) { syncedCam.UpdateBodyCamTarget(); }); } private void Awake() { SyncBodyCamToRadarMap[] allSynchronizedCams = AllSynchronizedCams; int num = 0; SyncBodyCamToRadarMap[] array = new SyncBodyCamToRadarMap[1 + allSynchronizedCams.Length]; ReadOnlySpan readOnlySpan = new ReadOnlySpan(allSynchronizedCams); readOnlySpan.CopyTo(new Span(array).Slice(num, readOnlySpan.Length)); num += readOnlySpan.Length; array[num] = this; AllSynchronizedCams = array; if ((Object)(object)MapRenderer == (Object)null) { MapRenderer = ((Component)this).GetComponentsInChildren()?.FirstOrDefault((Func)((ManualCameraRenderer renderer) => (Object)(object)renderer.cam == (Object)(object)renderer.mapCamera)); } if ((Object)(object)BodyCam == (Object)null) { BodyCam = ((Component)this).GetComponent(); } } private void Start() { UpdateBodyCamTarget(); } private void OnEnable() { if ((Object)(object)BodyCam != (Object)null && (Object)(object)MapRenderer != (Object)null) { UpdateBodyCamTarget(); } } private void Update() { BodyCam.ForceTargetInvalid = MapRenderer.playerIsInCaves; } public void UpdateBodyCamTarget() { if (((Behaviour)this).isActiveAndEnabled) { if ((Object)(object)MapRenderer.targetedPlayer != (Object)null) { BodyCam.SetTargetToPlayer(MapRenderer.targetedPlayer); } else { BodyCam.SetTargetToTransform(MapRenderer.radarTargets[MapRenderer.targetTransformIndex].transform); } BodyCam.SetScreenPowered(MapRenderer.isScreenOn); } } public void StartTargetTransition() { if (((Behaviour)this).isActiveAndEnabled) { BodyCam.StartTargetTransition(); } } internal static void OnBodyCamDestroyed(BodyCamComponent bodyCam) { DoForCam(bodyCam, (Action)Object.Destroy); } private void OnDestroy() { AllSynchronizedCams = AllSynchronizedCams.Where((SyncBodyCamToRadarMap syncedCam) => syncedCam != this).ToArray(); } } public static class TerminalCommands { private static TerminalNode ViewMonitorNode; private static TerminalNode ViewBodyCamNode; private static TerminalKeyword BodyCamKeyword; private static TerminalNode BodyCamFailedNode; private static TerminalNode BodyCamLockedNode; private static RawImage PiPImage; private static readonly List newTerminalKeywords = new List(); private static readonly Dictionary> addedCompatibleNouns = new Dictionary>(); public static void Initialize() { //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Expected O, but got Unknown //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Unknown result type (might be due to invalid IL or missing references) //IL_0207: Unknown result type (might be due to invalid IL or missing references) //IL_0208: Unknown result type (might be due to invalid IL or missing references) //IL_0218: Unknown result type (might be due to invalid IL or missing references) //IL_021d: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_022e: Unknown result type (might be due to invalid IL or missing references) //IL_022f: Unknown result type (might be due to invalid IL or missing references) //IL_0231: Unknown result type (might be due to invalid IL or missing references) //IL_0245: Unknown result type (might be due to invalid IL or missing references) //IL_0246: Unknown result type (might be due to invalid IL or missing references) //IL_0248: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ShipObjects.TerminalScript == (Object)null || (Object)(object)ShipObjects.MainBodyCam == (Object)null) { return; } if ((Object)(object)PiPImage != (Object)null) { Object.Destroy((Object)(object)((Component)PiPImage).gameObject); } PiPImage = null; ShipObjects.MainBodyCam.OnRenderTextureCreated -= SetRenderTexture; ShipObjects.MainBodyCam.OnBlankedSet -= SetBodyCamBlanked; BodyCam.OnBodyCamReceiverBecameDisabled -= DisablePiPImage; if (Plugin.TerminalPiPBodyCamEnabled.Value) { GameObject val = new GameObject("PictureInPictureImage"); val.transform.SetParent(((Component)ShipObjects.TerminalScript.terminalImageMask).transform, false); PiPImage = val.AddComponent(); val.AddComponent().BodyCamToActivate = ShipObjects.MainBodyCam; RectTransform rectTransform = ((Graphic)ShipObjects.TerminalScript.terminalImage).rectTransform; Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(0f, 0f); Vector2 val3 = default(Vector2); ((Vector2)(ref val3))..ctor(1f, 1f); int value = (int)Plugin.TerminalPiPPosition.Value; ref float x = ref val2.x; ref float x2 = ref val3.x; (float, int) tuple = ((((uint)value & (true ? 1u : 0u)) != 0) ? (rectTransform.offsetMax.x, -1) : (rectTransform.offsetMin.x, 1)); (float, int) tuple2 = tuple; float num = tuple2.Item2; x = tuple2.Item1; x2 = num; ref float y = ref val2.y; ref float y2 = ref val3.y; (float, int) tuple3 = ((((uint)value & 2u) != 0) ? (rectTransform.offsetMax.y, -1) : (rectTransform.offsetMin.y, 1)); (float, int) tuple4 = tuple3; float num2 = tuple4.Item2; y = tuple4.Item1; y2 = num2; Vector2 val4 = val2 + new Vector2(1f, 0.75f) * val3 * (float)Plugin.TerminalPiPWidth.Value; ((Graphic)PiPImage).rectTransform.offsetMin = Vector2.Min(val2, val4); ((Graphic)PiPImage).rectTransform.offsetMax = Vector2.Max(val2, val4); if ((Object)(object)ShipObjects.MainBodyCam.Camera != (Object)null) { PiPImage.texture = (Texture)(object)ShipObjects.MainBodyCam.Camera.targetTexture; } ShipObjects.MainBodyCam.OnRenderTextureCreated += SetRenderTexture; ShipObjects.MainBodyCam.OnBlankedSet += SetBodyCamBlanked; BodyCam.OnBodyCamReceiverBecameDisabled += DisablePiPImage; val.SetActive(false); } InitializeCommands(); } public static void SetRenderTexture(RenderTexture texture) { PiPImage.texture = (Texture)(object)texture; } public static void SetBodyCamBlanked(bool blanked) { ((Behaviour)PiPImage).enabled = !blanked; } private static void DisablePiPImage() { ((Component)PiPImage).gameObject.SetActive(false); } private static void EnablePiPImage() { ((Component)PiPImage).gameObject.SetActive(true); } private static void InitializeCommands() { //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Expected O, but got Unknown RemoveAddedKeywords(); ViewBodyCamNode = null; BodyCamKeyword = null; TerminalKeyword val = FindKeyword("view", verb: true); ViewMonitorNode = ((val == null) ? null : val.FindCompatibleNoun("monitor")?.result); if (Plugin.TerminalPiPBodyCamEnabled.Value) { if ((Object)(object)ViewMonitorNode == (Object)null) { Plugin.Instance.Logger.LogWarning((object)"'view monitor' command does not exist, terminal PiP body cam view will be disabled."); return; } ViewBodyCamNode = ScriptableObject.CreateInstance(); ((Object)ViewBodyCamNode).name = "ViewBodyCam"; ViewBodyCamNode.displayText = "Toggling picture-in-picture body cam.\n\n"; ViewBodyCamNode.clearPreviousText = true; BodyCamKeyword = FindOrCreateKeyword("BodyCam", "bodycam", verb: false); AddCompatibleNoun(val, BodyCamKeyword, ViewBodyCamNode); CompatibleNoun[] array = val.compatibleNouns ?? Array.Empty(); int num = 0; CompatibleNoun[] array2 = (CompatibleNoun[])(object)new CompatibleNoun[1 + array.Length]; ReadOnlySpan readOnlySpan = new ReadOnlySpan(array); readOnlySpan.CopyTo(new Span(array2).Slice(num, readOnlySpan.Length)); num += readOnlySpan.Length; array2[num] = new CompatibleNoun(BodyCamKeyword, ViewBodyCamNode); val.compatibleNouns = array2; BodyCamFailedNode = ScriptableObject.CreateInstance(); ((Object)BodyCamFailedNode).name = "BodyCamFailed"; BodyCamFailedNode.displayText = "Map view is currently disabled.\n\n"; BodyCamFailedNode.clearPreviousText = true; BodyCamLockedNode = ScriptableObject.CreateInstance(); ((Object)BodyCamLockedNode).name = "BodyCamFailed"; BodyCamLockedNode.displayText = "Please place a body cams receiver antenna on the ship.\n\n"; BodyCamLockedNode.clearPreviousText = true; } AddNewlyCreatedCommands(); } private static bool TerminalIsDisplayingMap() { if ((Object)(object)ViewMonitorNode == (Object)null) { return false; } return (Object)(object)ShipObjects.TerminalScript.displayingPersistentImage == (Object)(object)ViewMonitorNode.displayTexture; } internal static bool TerminalIsDisplayingBodyCam() { if ((Object)(object)PiPImage == (Object)null) { return false; } return ((Component)PiPImage).gameObject.activeSelf; } [HarmonyPrefix] [HarmonyPatch(typeof(Terminal), "LoadNewNode")] private static void LoadNewNodePrefix(ref TerminalNode node) { if ((Object)(object)node == (Object)null || !((Object)(object)node == (Object)(object)ViewBodyCamNode)) { return; } if (TerminalIsDisplayingBodyCam()) { DisablePiPImage(); return; } if (!BodyCam.BodyCamsAreAvailable) { node = BodyCamLockedNode; return; } if (!TerminalIsDisplayingMap()) { ShipObjects.TerminalScript.LoadTerminalImage(ViewMonitorNode); } if (!TerminalIsDisplayingMap()) { node = BodyCamFailedNode; } else { EnablePiPImage(); } } [HarmonyPostfix] [HarmonyPatch(typeof(Terminal), "LoadNewNode")] private static void LoadNewNodePostfix(TerminalNode node) { if (!((Object)(object)PiPImage == (Object)null) && !((Object)(object)node != (Object)(object)ViewMonitorNode) && !TerminalIsDisplayingMap()) { DisablePiPImage(); } } [HarmonyPostfix] [HarmonyPatch(typeof(StartOfRound), "SwitchMapMonitorPurpose")] private static void SwitchMapMonitorPurposePostfix() { if (!((Object)(object)PiPImage == (Object)null) && !TerminalIsDisplayingMap()) { DisablePiPImage(); } } private static TerminalKeyword FindKeyword(string word, bool verb) { return ((IEnumerable)ShipObjects.TerminalScript.terminalNodes.allKeywords).FirstOrDefault((Func)((TerminalKeyword keyword) => keyword.word == word && keyword.isVerb == verb)); } private static CompatibleNoun FindCompatibleNoun(this TerminalKeyword keyword, string noun) { return ((IEnumerable)keyword.compatibleNouns).FirstOrDefault((Func)((CompatibleNoun compatible) => compatible.noun.word == noun)); } private static TerminalKeyword FindOrCreateKeyword(string name, string word, bool verb, CompatibleNoun[] compatibleNouns = null) { Plugin.Instance.Logger.LogInfo((object)("Creating terminal " + (verb ? "verb" : "noun") + " '" + word + "' (" + name + ").")); TerminalKeyword val = FindKeyword(word, verb); if ((Object)(object)val == (Object)null) { val = ScriptableObject.CreateInstance(); ((Object)val).name = name; val.isVerb = verb; val.word = word; val.compatibleNouns = compatibleNouns; newTerminalKeywords.Add(val); Plugin.Instance.Logger.LogInfo((object)" Keyword was not found, created a new one."); } else if (compatibleNouns != null) { foreach (CompatibleNoun compatibleNoun in compatibleNouns) { AddCompatibleNoun(val, compatibleNoun); } Plugin.Instance.Logger.LogInfo((object)" Keyword existed, appended nouns."); } return val; } private static void AddCompatibleNoun(TerminalKeyword keyword, CompatibleNoun compatibleNoun) { if (!addedCompatibleNouns.TryGetValue(keyword, out var value)) { value = new List(); addedCompatibleNouns[keyword] = value; } CompatibleNoun[] array = keyword.compatibleNouns ?? Array.Empty(); int num = 0; CompatibleNoun[] array2 = (CompatibleNoun[])(object)new CompatibleNoun[1 + array.Length]; ReadOnlySpan readOnlySpan = new ReadOnlySpan(array); readOnlySpan.CopyTo(new Span(array2).Slice(num, readOnlySpan.Length)); num += readOnlySpan.Length; array2[num] = compatibleNoun; keyword.compatibleNouns = array2; value.Add(compatibleNoun.noun); } private static void AddCompatibleNoun(TerminalKeyword keyword, TerminalKeyword compatibleKeyword, TerminalNode result) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown AddCompatibleNoun(keyword, new CompatibleNoun(compatibleKeyword, result)); } private static void AddNewlyCreatedCommands() { TerminalNodesList terminalNodes = ShipObjects.TerminalScript.terminalNodes; TerminalNodesList val = terminalNodes; TerminalKeyword[] allKeywords = terminalNodes.allKeywords; List list = newTerminalKeywords; int num = 0; TerminalKeyword[] array = (TerminalKeyword[])(object)new TerminalKeyword[allKeywords.Length + list.Count]; ReadOnlySpan readOnlySpan = new ReadOnlySpan(allKeywords); readOnlySpan.CopyTo(new Span(array).Slice(num, readOnlySpan.Length)); num += readOnlySpan.Length; foreach (TerminalKeyword item in list) { array[num] = item; num++; } val.allKeywords = array; } private static void RemoveAddedKeywords() { foreach (KeyValuePair> addedCompatibleNoun in addedCompatibleNouns) { var (val2, addedNouns) = (KeyValuePair>)(ref addedCompatibleNoun); if (val2.compatibleNouns != null) { val2.compatibleNouns = val2.compatibleNouns.Where((CompatibleNoun compatible) => !addedNouns.Contains(compatible.noun)).ToArray(); } } addedCompatibleNouns.Clear(); TerminalNodesList terminalNodes = ShipObjects.TerminalScript.terminalNodes; terminalNodes.allKeywords = terminalNodes.allKeywords.Where((TerminalKeyword keyword) => !newTerminalKeywords.Contains(keyword)).ToArray(); foreach (TerminalKeyword newTerminalKeyword in newTerminalKeywords) { Object.Destroy((Object)(object)newTerminalKeyword); } newTerminalKeywords.Clear(); } } public enum PiPPosition : uint { BottomLeft, BottomRight, TopLeft, TopRight } public class TerminalBodyCamVisibilityTracker : MonoBehaviour { public BodyCamComponent BodyCamToActivate; private void OnEnable() { if ((Object)(object)BodyCamToActivate != (Object)null) { BodyCamToActivate.ForceEnableCamera = true; } } private void OnDisable() { if ((Object)(object)BodyCamToActivate != (Object)null) { BodyCamToActivate.ForceEnableCamera = false; } } } } namespace OpenBodyCams.Utilities { internal static class Cosmetics { [Flags] private enum CompatibilityMode { None = 0, MoreCompany = 1, AdvancedCompany = 4, ModelReplacementAPI = 8, LethalVRM = 0x10, ReservedItemSlots = 0x20 } internal static bool PrintDebugInfo; private static CompatibilityMode compatibilityMode; public static void Initialize(Harmony harmony) { bool flag = Chainloader.PluginInfos.ContainsKey("com.potatoepet.AdvancedCompany"); if (Plugin.EnableAdvancedCompanyCosmeticsCompatibility.Value && flag) { if (AdvancedCompanyCompatibility.Initialize(harmony)) { compatibilityMode |= CompatibilityMode.AdvancedCompany; Plugin.Instance.Logger.LogInfo((object)"AdvancedCompany compatibility mode is enabled."); } else { Plugin.Instance.Logger.LogWarning((object)"AdvancedCompany is installed, but the compatibility feature failed to initialize."); } } if (Plugin.EnableMoreCompanyCosmeticsCompatibility.Value && !flag && Chainloader.PluginInfos.ContainsKey("me.swipez.melonloader.morecompany")) { if (MoreCompanyCompatibility.Initialize(harmony)) { compatibilityMode |= CompatibilityMode.MoreCompany; Plugin.Instance.Logger.LogInfo((object)"MoreCompany compatibility mode is enabled."); } else { Plugin.Instance.Logger.LogWarning((object)"MoreCompany is installed, but the compatibility feature failed to initialize."); } } if (Plugin.EnableModelReplacementAPICompatibility.Value && Chainloader.PluginInfos.ContainsKey("meow.ModelReplacementAPI")) { if (ModelReplacementAPICompatibility.Initialize(harmony)) { compatibilityMode |= CompatibilityMode.ModelReplacementAPI; Plugin.Instance.Logger.LogInfo((object)"ModelReplacementAPI compatibility mode is enabled."); } else { Plugin.Instance.Logger.LogWarning((object)"ModelReplacementAPI is installed, but the compatibility feature failed to initialize."); } } if (Plugin.EnableLethalVRMCompatibility.Value && Chainloader.PluginInfos.ContainsKey("Ooseykins.LethalVRM")) { if (LethalVRMCompatibility.Initialize(harmony)) { compatibilityMode |= CompatibilityMode.LethalVRM; Plugin.Instance.Logger.LogInfo((object)"LethalVRM compatibility mode is enabled."); } else { Plugin.Instance.Logger.LogWarning((object)"LethalVRM is installed, but the compatibility feature failed to initialize."); } } if (Plugin.EnableReservedItemSlotsCompatibility.Value && Chainloader.PluginInfos.ContainsKey("FlipMods.ReservedItemSlotCore")) { if (ReservedItemSlotsCompatibility.Initialize(harmony)) { compatibilityMode |= CompatibilityMode.ReservedItemSlots; Plugin.Instance.Logger.LogInfo((object)"ReservedItemSlots compatibility mode is enabled."); } else { Plugin.Instance.Logger.LogWarning((object)"ReservedItemSlotCore is installed, but the compatibility feature failed to initialize."); } } } internal static List CollectVanillaFirstPersonCosmetics(PlayerControllerB player) { Renderer[] componentsInChildren = ((Component)player.headCostumeContainerLocal).GetComponentsInChildren(); List list = new List(componentsInChildren.Length); for (int i = 0; i < componentsInChildren.Length; i++) { list.Add(((Component)componentsInChildren[i]).gameObject); } return list; } internal static List CollectVanillaThirdPersonCosmetics(PlayerControllerB player) { Renderer[] componentsInChildren = ((Component)player.headCostumeContainer).GetComponentsInChildren(); Renderer[] componentsInChildren2 = ((Component)player.lowerTorsoCostumeContainer).GetComponentsInChildren(); List list = new List(componentsInChildren.Length + componentsInChildren2.Length); for (int i = 0; i < componentsInChildren.Length; i++) { list.Add(((Component)componentsInChildren[i]).gameObject); } for (int j = 0; j < componentsInChildren2.Length; j++) { list.Add(((Component)componentsInChildren2[j]).gameObject); } return list; } private static void DoCollectCosmetics(PlayerControllerB player, out GameObject[] thirdPersonCosmetics, out GameObject[] firstPersonCosmetics, out bool hasViewmodelReplacement) { if ((Object)(object)player == (Object)null) { thirdPersonCosmetics = Array.Empty(); firstPersonCosmetics = Array.Empty(); hasViewmodelReplacement = false; return; } double num = 0.0; if (PrintDebugInfo) { num = Time.realtimeSinceStartupAsDouble; } List list = CollectVanillaThirdPersonCosmetics(player); List list2 = CollectVanillaFirstPersonCosmetics(player); hasViewmodelReplacement = false; BodyCam.CollectPlayerThirdPersonCosmetics(player, list); BodyCam.CollectPlayerFirstPersonCosmetics(player, list2, ref hasViewmodelReplacement); if (compatibilityMode.HasFlag(CompatibilityMode.MoreCompany)) { MoreCompanyCompatibility.CollectCosmetics(player, list); } if (compatibilityMode.HasFlag(CompatibilityMode.AdvancedCompany)) { AdvancedCompanyCompatibility.CollectCosmetics(player, list); } if (compatibilityMode.HasFlag(CompatibilityMode.LethalVRM)) { LethalVRMCompatibility.CollectCosmetics(player, list); } if (compatibilityMode.HasFlag(CompatibilityMode.ModelReplacementAPI)) { ModelReplacementAPICompatibility.CollectCosmetics(player, list, list2, ref hasViewmodelReplacement); } if (compatibilityMode.HasFlag(CompatibilityMode.ReservedItemSlots)) { ReservedItemSlotsCompatibility.CollectCosmetics(player, list); } thirdPersonCosmetics = list.ToArray(); firstPersonCosmetics = list2.ToArray(); if (PrintDebugInfo) { double num2 = (Time.realtimeSinceStartupAsDouble - num) * 1000000.0; Plugin.Instance.Logger.LogInfo((object)string.Format("Collected {0} third-person and {1} cosmetics for {2} with{3} a viewmodel replacement in {4:0.##} microseconds.", thirdPersonCosmetics.Length, firstPersonCosmetics.Length, player.playerUsername, hasViewmodelReplacement ? "" : "out", num2)); } } public static void CollectCosmetics(PlayerControllerB player, out GameObject[] thirdPersonCosmetics, out GameObject[] firstPersonCosmetics, out bool hasViewmodelReplacement) { try { DoCollectCosmetics(player, out thirdPersonCosmetics, out firstPersonCosmetics, out hasViewmodelReplacement); } catch (Exception ex) { Plugin.Instance.Logger.LogError((object)("Failed to get third-person cosmetics for player " + player.playerUsername + ":")); Plugin.Instance.Logger.LogError((object)ex); thirdPersonCosmetics = Array.Empty(); firstPersonCosmetics = Array.Empty(); hasViewmodelReplacement = false; } } internal static void CollectChildCosmetics(GameObject obj, List children) { Renderer[] componentsInChildren = obj.GetComponentsInChildren(); foreach (Renderer val in componentsInChildren) { children.Add(((Component)val).gameObject); } } } internal static class MeshUtils { private static Mesh MakeReadableMeshCopy(Mesh nonReadableMesh) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: 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_0012: Expected O, but got Unknown //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) Mesh val = new Mesh { indexFormat = nonReadableMesh.indexFormat }; nonReadableMesh.vertexBufferTarget = (Target)1; if (nonReadableMesh.vertexBufferCount > 0) { GraphicsBuffer vertexBuffer = nonReadableMesh.GetVertexBuffer(0); try { int num = vertexBuffer.stride * vertexBuffer.count; byte[] array = new byte[num]; vertexBuffer.GetData((Array)array); val.SetVertexBufferParams(nonReadableMesh.vertexCount, nonReadableMesh.GetVertexAttributes()); val.SetVertexBufferData(array, 0, 0, num, 0, (MeshUpdateFlags)0); } finally { ((IDisposable)vertexBuffer)?.Dispose(); } } nonReadableMesh.indexBufferTarget = (Target)2; val.subMeshCount = nonReadableMesh.subMeshCount; GraphicsBuffer indexBuffer = nonReadableMesh.GetIndexBuffer(); try { int num2 = indexBuffer.stride * indexBuffer.count; byte[] array2 = new byte[num2]; indexBuffer.GetData((Array)array2); val.SetIndexBufferParams(indexBuffer.count, nonReadableMesh.indexFormat); val.SetIndexBufferData(array2, 0, 0, num2, (MeshUpdateFlags)0); indexBuffer.Release(); } finally { ((IDisposable)indexBuffer)?.Dispose(); } int num3 = 0; for (int i = 0; i < val.subMeshCount; i++) { int indexCount = (int)nonReadableMesh.GetIndexCount(i); val.SetSubMesh(i, new SubMeshDescriptor(num3, indexCount, (MeshTopology)0), (MeshUpdateFlags)0); num3 += indexCount; } return val; } internal static Mesh CopySubmesh(Mesh mesh, int submesh) { //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Expected O, but got Unknown //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) if (!mesh.isReadable) { mesh = MakeReadableMeshCopy(mesh); } Dictionary dictionary = new Dictionary(); Vector3[] vertices = mesh.vertices; int[] triangles = mesh.GetTriangles(submesh); Vector2[] uv = mesh.uv; List list = new List(vertices.Length); List list2 = new List(uv.Length); int[] array = new int[triangles.Length]; for (int i = 0; i < triangles.Length; i++) { int num = triangles[i]; if (!dictionary.TryGetValue(num, out var value)) { value = (dictionary[num] = list.Count); list.Add(vertices[num]); list2.Add(uv[num]); } array[i] = value; } return new Mesh { vertices = list.ToArray(), uv = list2.ToArray(), triangles = array }; } } public static class Utilities { private static Camera[] allCameras = Array.Empty(); private static readonly Plane[] frustumPlanes = (Plane[])(object)new Plane[6]; private static Queue transformQueue = new Queue(); public static bool IsVisibleToAnyCameraExcept(this Renderer renderer, Camera cameraToSkip) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) if (allCameras.Length != Camera.allCamerasCount) { allCameras = (Camera[])(object)new Camera[Camera.allCamerasCount]; } Camera.GetAllCameras(allCameras); Bounds bounds = renderer.bounds; int layer = ((Component)renderer).gameObject.layer; Camera[] array = allCameras; foreach (Camera val in array) { if ((val == null || val != cameraToSkip) && (val.cullingMask & (1 << layer)) != 0) { GeometryUtility.CalculateFrustumPlanes(val, frustumPlanes); if (GeometryUtility.TestPlanesAABB(frustumPlanes, bounds)) { return true; } } } return false; } public static void SetMaterial(this Renderer renderer, int index, Material material) { Material[] sharedMaterials = renderer.sharedMaterials; sharedMaterials[index] = material; renderer.sharedMaterials = sharedMaterials; } public static T GetComponentInChildrenBreadthFirst(this Component self, Func predicate) where T : Component { transformQueue.Clear(); transformQueue.Enqueue(self.transform); Transform result; while (transformQueue.TryDequeue(out result)) { T[] components = ((Component)result).GetComponents(); foreach (T val in components) { if (predicate == null || predicate(val)) { return val; } } for (int j = 0; j < result.childCount; j++) { transformQueue.Enqueue(result.GetChild(j)); } } return default(T); } } public enum Perspective { Original, FirstPerson, ThirdPerson } public static class ViewPerspective { public const int DEFAULT_LAYER = 0; public const int ENEMIES_LAYER = 19; public const int ENEMIES_NOT_RENDERED_LAYER = 23; private static void SetCosmeticHidden(GameObject cosmetic, bool hidden) { cosmetic.layer = (hidden ? 23 : 0); } public static void PrepareModelState(PlayerControllerB player, ref PlayerModelState state) { Restore(ref state); state.player = player; state.lastPerspective = Perspective.Original; if (player == null) { state.thirdPersonCosmetics = Array.Empty(); state.thirdPersonCosmeticsLayers = Array.Empty(); state.thirdPersonCosmeticNames = Array.Empty(); state.firstPersonCosmetics = Array.Empty(); state.firstPersonCosmeticsLayers = Array.Empty(); state.firstPersonCosmeticNames = Array.Empty(); } else { Cosmetics.CollectCosmetics(player, out state.thirdPersonCosmetics, out state.firstPersonCosmetics, out state.hasViewmodelReplacement); state.thirdPersonCosmeticsLayers = new int[state.thirdPersonCosmetics.Length]; state.thirdPersonCosmeticNames = GetCosmeticsPaths(state.thirdPersonCosmetics, ((Component)player.playerBodyAnimator).transform); state.firstPersonCosmeticsLayers = new int[state.firstPersonCosmetics.Length]; state.firstPersonCosmeticNames = GetCosmeticsPaths(state.firstPersonCosmetics, ((Component)player.playerBodyAnimator).transform); } } public static void Apply(ref PlayerModelState state, Perspective perspective) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_007d: 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_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) PlayerControllerB player = state.player; if (player == null) { return; } Restore(ref state); if (perspective == Perspective.Original) { return; } state.thirdPersonBodyShadowMode = ((Renderer)player.thisPlayerModel).shadowCastingMode; state.thirdPersonBodyLayer = ((Component)player.thisPlayerModel).gameObject.layer; state.firstPersonArmsEnabled = ((Renderer)player.thisPlayerModelArms).enabled; state.firstPersonArmsLayer = ((Component)player.thisPlayerModelArms).gameObject.layer; if ((Object)(object)player.currentlyHeldObjectServer != (Object)null) { state.heldItemPosition = ((Component)player.currentlyHeldObjectServer).transform.position; state.heldItemRotation = ((Component)player.currentlyHeldObjectServer).transform.rotation; GrabbableObject currentlyHeldObjectServer = player.currentlyHeldObjectServer; FlashlightItem val = (FlashlightItem)(object)((currentlyHeldObjectServer is FlashlightItem) ? currentlyHeldObjectServer : null); if (val != null) { state.helmetLightEnabled = ((Behaviour)player.helmetLight).enabled; state.heldLightEnabled = ((Behaviour)val.flashlightBulb).enabled; } } for (int i = 0; i < state.thirdPersonCosmetics.Length; i++) { if ((Object)(object)state.thirdPersonCosmetics[i] == (Object)null) { ref string reference = ref state.thirdPersonCosmeticNames[i]; if (reference != null) { Plugin.Instance.Logger.LogWarning((object)$"{player.playerUsername}'s third-person cosmetic {reference} is null.\n{new StackTrace()}"); reference = null; } } else { state.thirdPersonCosmeticsLayers[i] = state.thirdPersonCosmetics[i].layer; } } for (int j = 0; j < state.firstPersonCosmetics.Length; j++) { if ((Object)(object)state.firstPersonCosmetics[j] == (Object)null) { ref string reference2 = ref state.firstPersonCosmeticNames[j]; if (reference2 != null) { Plugin.Instance.Logger.LogWarning((object)$"{player.playerUsername}'s first-person cosmetic {reference2} is null.\n{new StackTrace()}"); reference2 = null; } } else { state.firstPersonCosmeticsLayers[j] = state.firstPersonCosmetics[j].layer; } } switch (perspective) { case Perspective.FirstPerson: { ((Renderer)player.thisPlayerModel).shadowCastingMode = (ShadowCastingMode)3; ((Component)player.thisPlayerModel).gameObject.layer = 23; if (!state.hasViewmodelReplacement) { ((Renderer)player.thisPlayerModelArms).enabled = true; ((Component)player.thisPlayerModelArms).gameObject.layer = 0; } if ((Object)(object)player.currentlyHeldObjectServer != (Object)null) { AttachItem(player.currentlyHeldObjectServer, player.localItemHolder); GrabbableObject currentlyHeldObjectServer3 = player.currentlyHeldObjectServer; FlashlightItem val5 = (FlashlightItem)(object)((currentlyHeldObjectServer3 is FlashlightItem) ? currentlyHeldObjectServer3 : null); if (val5 != null) { ((Behaviour)player.helmetLight).enabled = false; ((Behaviour)val5.flashlightBulb).enabled = ((GrabbableObject)val5).isBeingUsed; ((Behaviour)val5.flashlightBulbGlow).enabled = ((GrabbableObject)val5).isBeingUsed; } } GameObject[] thirdPersonCosmetics2 = state.thirdPersonCosmetics; foreach (GameObject val6 in thirdPersonCosmetics2) { if (!((Object)(object)val6 == (Object)null)) { SetCosmeticHidden(val6, hidden: true); } } GameObject[] firstPersonCosmetics2 = state.firstPersonCosmetics; foreach (GameObject val7 in firstPersonCosmetics2) { if (!((Object)(object)val7 == (Object)null)) { SetCosmeticHidden(val7, hidden: false); } } break; } case Perspective.ThirdPerson: { ((Renderer)player.thisPlayerModel).shadowCastingMode = (ShadowCastingMode)1; ((Component)player.thisPlayerModel).gameObject.layer = 0; if (!state.hasViewmodelReplacement) { ((Renderer)player.thisPlayerModelArms).enabled = false; ((Component)player.thisPlayerModelArms).gameObject.layer = 23; } if ((Object)(object)player.currentlyHeldObjectServer != (Object)null) { AttachItem(player.currentlyHeldObjectServer, player.serverItemHolder); GrabbableObject currentlyHeldObjectServer2 = player.currentlyHeldObjectServer; FlashlightItem val2 = (FlashlightItem)(object)((currentlyHeldObjectServer2 is FlashlightItem) ? currentlyHeldObjectServer2 : null); if (val2 != null) { ((Behaviour)player.helmetLight).enabled = ((GrabbableObject)val2).isBeingUsed; ((Behaviour)val2.flashlightBulb).enabled = false; ((Behaviour)val2.flashlightBulbGlow).enabled = false; } } GameObject[] thirdPersonCosmetics = state.thirdPersonCosmetics; foreach (GameObject val3 in thirdPersonCosmetics) { if (!((Object)(object)val3 == (Object)null)) { SetCosmeticHidden(val3, hidden: false); } } GameObject[] firstPersonCosmetics = state.firstPersonCosmetics; foreach (GameObject val4 in firstPersonCosmetics) { if (!((Object)(object)val4 == (Object)null)) { SetCosmeticHidden(val4, hidden: true); } } break; } } PatchFlowerSnakeEnemy.SetClingingAnimationPositionsForPlayer(player, perspective); PatchCentipedeAI.SetClingingAnimationPositionsForPlayer(player, perspective); state.lastPerspective = perspective; static void AttachItem(GrabbableObject item, Transform holder) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) ((Component)item).transform.rotation = holder.rotation; ((Component)item).transform.Rotate(item.itemProperties.rotationOffset); ((Component)item).transform.position = holder.position + holder.rotation * item.itemProperties.positionOffset; } } public static void Restore(ref PlayerModelState state) { //IL_001a: 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_0101: Unknown result type (might be due to invalid IL or missing references) PlayerControllerB player = state.player; if (player == null || state.lastPerspective == Perspective.Original) { return; } ((Renderer)player.thisPlayerModel).shadowCastingMode = state.thirdPersonBodyShadowMode; ((Component)player.thisPlayerModel).gameObject.layer = state.thirdPersonBodyLayer; ((Renderer)player.thisPlayerModelArms).enabled = state.firstPersonArmsEnabled; ((Component)player.thisPlayerModelArms).gameObject.layer = state.firstPersonArmsLayer; for (int i = 0; i < state.thirdPersonCosmetics.Length; i++) { if (!((Object)(object)state.thirdPersonCosmetics[i] == (Object)null)) { state.thirdPersonCosmetics[i].layer = state.thirdPersonCosmeticsLayers[i]; } } for (int j = 0; j < state.firstPersonCosmetics.Length; j++) { if (!((Object)(object)state.firstPersonCosmetics[j] == (Object)null)) { state.firstPersonCosmetics[j].layer = state.firstPersonCosmeticsLayers[j]; } } if ((Object)(object)player.currentlyHeldObjectServer != (Object)null) { ((Component)player.currentlyHeldObjectServer).transform.position = state.heldItemPosition; ((Component)player.currentlyHeldObjectServer).transform.rotation = state.heldItemRotation; GrabbableObject currentlyHeldObjectServer = player.currentlyHeldObjectServer; FlashlightItem val = (FlashlightItem)(object)((currentlyHeldObjectServer is FlashlightItem) ? currentlyHeldObjectServer : null); if (val != null) { ((Behaviour)player.helmetLight).enabled = state.helmetLightEnabled; ((Behaviour)val.flashlightBulb).enabled = state.heldLightEnabled; ((Behaviour)val.flashlightBulbGlow).enabled = state.heldLightEnabled; } } PatchFlowerSnakeEnemy.SetClingingAnimationPositionsForPlayer(player, Perspective.Original); PatchCentipedeAI.SetClingingAnimationPositionsForPlayer(player, Perspective.Original); state.lastPerspective = Perspective.Original; } private static string[] GetCosmeticsPaths(GameObject[] objects, Transform root) { string[] array = new string[objects.Length]; for (int i = 0; i < objects.Length; i++) { Transform val = objects[i].transform; StringBuilder stringBuilder = new StringBuilder(((Object)val).name); do { val = val.parent; if ((Object)(object)val == (Object)null || (Object)(object)val == (Object)(object)root) { break; } stringBuilder.Insert(0, '/'); stringBuilder.Insert(0, ((Object)val).name); } while (!((Object)val).name.EndsWith("(Clone)")); array[i] = stringBuilder.ToString(); } return array; } } public struct PlayerModelState { internal PlayerControllerB player; internal Perspective lastPerspective; internal ShadowCastingMode thirdPersonBodyShadowMode; internal int thirdPersonBodyLayer; internal bool firstPersonArmsEnabled; internal int firstPersonArmsLayer; internal GameObject[] thirdPersonCosmetics; internal int[] thirdPersonCosmeticsLayers; internal string[] thirdPersonCosmeticNames; internal GameObject[] firstPersonCosmetics; internal int[] firstPersonCosmeticsLayers; internal string[] firstPersonCosmeticNames; internal bool hasViewmodelReplacement; internal Vector3 heldItemPosition; internal Quaternion heldItemRotation; internal bool helmetLightEnabled; internal bool heldLightEnabled; public PlayerModelState() { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) player = null; thirdPersonBodyShadowMode = (ShadowCastingMode)0; thirdPersonBodyLayer = 0; firstPersonArmsEnabled = false; firstPersonArmsLayer = 0; heldItemPosition = default(Vector3); heldItemRotation = default(Quaternion); helmetLightEnabled = false; heldLightEnabled = false; lastPerspective = Perspective.Original; thirdPersonCosmetics = Array.Empty(); thirdPersonCosmeticsLayers = Array.Empty(); thirdPersonCosmeticNames = Array.Empty(); firstPersonCosmetics = Array.Empty(); firstPersonCosmeticsLayers = Array.Empty(); firstPersonCosmeticNames = Array.Empty(); hasViewmodelReplacement = false; } private static bool AllObjectsExistInArray(GameObject[] objects) { foreach (GameObject val in objects) { if ((Object)(object)val == (Object)null) { return false; } } return true; } internal readonly bool VerifyCosmeticsExist(string name) { if ((Object)(object)player == (Object)null) { return true; } if (!AllObjectsExistInArray(thirdPersonCosmetics)) { Plugin.Instance.Logger.LogError((object)("A third-person cosmetic attached to " + name + " has been destroyed.")); return false; } if (!AllObjectsExistInArray(firstPersonCosmetics)) { Plugin.Instance.Logger.LogError((object)("A first-person cosmetic attached to " + name + " has been destroyed.")); return false; } return true; } internal readonly bool ReferencesObject(GameObject obj) { if ((Object)(object)player == (Object)null) { return false; } if (Array.IndexOf(thirdPersonCosmetics, obj) != -1) { return true; } if (Array.IndexOf(firstPersonCosmetics, obj) != -1) { return true; } return false; } } internal class WeatherEffectComponents { internal LevelWeatherType weatherType; internal WeatherEffect effect; internal GameObject effectObject; internal Behaviour[] behaviours = Array.Empty(); internal Renderer[] renderers = Array.Empty(); internal bool enabled; internal bool active; internal bool visible = true; internal Vector3 transitionPoint = Vector3.zero; internal int transitionFrame = -1; internal WeatherEffectComponents(LevelWeatherType weatherType, GameObject overrideEffectObject = null) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0036: 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_0047: Unknown result type (might be due to invalid IL or missing references) this.weatherType = weatherType; effect = TimeOfDay.Instance.effects[weatherType]; effectObject = overrideEffectObject ?? effect.effectObject; if ((Object)(object)effectObject != (Object)null) { behaviours = (from b in effectObject.GetComponentsInChildren() where b.enabled && (b is Light || b is LocalVolumetricFog) select b).ToArray(); renderers = (from r in effectObject.GetComponentsInChildren() where r.enabled select r).ToArray(); } } internal void SetVisibility(bool show) { visible = show; if (!((Object)(object)effectObject == (Object)null) && effectObject.activeInHierarchy) { Behaviour[] array = behaviours; foreach (Behaviour val in array) { val.enabled = show; } Renderer[] array2 = renderers; foreach (Renderer val2 in array2) { val2.enabled = show; } } } internal void Update(Transform target, bool isInInterior, float deltaTime) { //IL_0062: 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_003f: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) if (enabled) { if ((Object)(object)effectObject != (Object)null) { if (effect.lerpPosition) { effectObject.transform.position = Vector3.Lerp(effectObject.transform.position, target.position, Mathf.Clamp01(deltaTime)); } else { effectObject.transform.position = target.position; } SetActive(value: true); } transitionFrame = -1; } else if ((Object)(object)effectObject != (Object)null && effect.lerpPosition) { if (transitionFrame == -1) { transitionFrame = 0; transitionPoint = target.position; } } else { SetActive(value: false); transitionFrame = -1; } if (transitionFrame >= 0) { float num = Math.Min((float)transitionFrame / 270f, 1f); effectObject.transform.position = Vector3.Lerp(effectObject.transform.position, transitionPoint + Vector3.down * 50f, num); if (num < 1f) { transitionFrame++; SetActive(value: true); } else { SetActive(value: false); } } void SetActive(bool value) { if (value != active) { GameObject obj = effectObject; if (obj != null) { obj.SetActive(value); } active = value; if (value) { SetVisibility(visible); } } } } } } namespace OpenBodyCams.Utilities.IL { internal class ILInjector { [CompilerGenerated] private sealed class d__34 : IEnumerable, IEnumerable, IEnumerator, IEnumerator, IDisposable { private int <>1__state; private CodeInstruction <>2__current; private int <>l__initialThreadId; public ILInjector <>4__this; private int offset; public int <>3__offset; private int size; public int <>3__size; private int 5__2; CodeInstruction IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__34(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { int num = <>1__state; ILInjector iLInjector = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; 5__2 = 0; break; case 1: <>1__state = -1; 5__2++; break; } if (5__2 < size) { <>2__current = iLInjector.instructions[iLInjector.index + offset + 5__2]; <>1__state = 1; return true; } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { d__34 d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; d__ = this; } else { d__ = new d__34(0) { <>4__this = <>4__this }; } d__.offset = <>3__offset; d__.size = <>3__size; return d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)this).GetEnumerator(); } } private const string INVALID = "Injector is invalid"; private List instructions = instructions.ToList(); private ILGenerator generator; private int index; private int matchEnd; public int Index { get { return index; } set { index = value; } } public bool IsValid { get { if (instructions != null) { return IsIndexValid(index); } return false; } } public CodeInstruction Instruction { get { if (!IsIndexInRange(index)) { return null; } return instructions[index]; } set { if (!IsIndexInRange(index)) { throw new InvalidOperationException($"Current index {index} is out of range of instruction count {instructions.Count}"); } instructions[index] = value; } } public CodeInstruction LastMatchedInstruction { get { int num = matchEnd - 1; if (!IsIndexInRange(num)) { return null; } return instructions[num]; } set { int num = matchEnd - 1; if (!IsIndexInRange(num)) { throw new InvalidOperationException($"Last matched index {index} is out of range of instruction count {instructions.Count}"); } instructions[num] = value; } } public ICollection Instructions => instructions.AsReadOnly(); public ILInjector(IEnumerable instructions, ILGenerator generator = null) { this.generator = generator; matchEnd = -1; base..ctor(); } public ILInjector GoToStart() { matchEnd = index; index = 0; return this; } public ILInjector GoToEnd() { matchEnd = index; index = instructions.Count; return this; } public ILInjector Forward(int offset) { if (!IsValid) { return this; } matchEnd = index; index = Math.Clamp(index + offset, -1, instructions.Count); return this; } public ILInjector Back(int offset) { return Forward(-offset); } private void MarkInvalid() { index = -1; matchEnd = -1; } private void Search(bool forward, ILMatcher[] predicates) { if (!IsValid) { return; } int num = 1; if (!forward) { num = -1; index--; } while (forward ? (index < instructions.Count) : (index >= 0)) { if (forward && index + predicates.Length > instructions.Count) { index = instructions.Count; break; } int i; for (i = 0; i < predicates.Length && predicates[i].Matches(instructions[index + i]); i++) { } if (i == predicates.Length) { matchEnd = index + i; return; } index += num; } MarkInvalid(); } public ILInjector Find(params ILMatcher[] predicates) { Search(forward: true, predicates); return this; } public ILInjector ReverseFind(params ILMatcher[] predicates) { Search(forward: false, predicates); return this; } public ILInjector GoToPush(int popIndex) { if (!IsValid) { return this; } matchEnd = index; index--; int num = 0; while (index >= 0) { CodeInstruction instruction = instructions[index]; num += instruction.PushCount(); num -= instruction.PopCount(); if (num >= popIndex) { return this; } index--; } return this; } public ILInjector SkipBranch() { if (Instruction == null) { return this; } if (!(Instruction.operand is Label label)) { throw new InvalidOperationException($"Current instruction is not a branch: {Instruction}"); } return FindLabel(label); } public ILInjector FindLabel(Label label) { if (label == default(Label)) { return this; } matchEnd = index; for (index = 0; index < instructions.Count; index++) { if (instructions[index].labels.Contains(label)) { return this; } } MarkInvalid(); return this; } public ILInjector GoToMatchEnd() { index = matchEnd; return this; } public ILInjector GoToLastMatchedInstruction() { if (!IsIndexValid(matchEnd)) { return this; } index = matchEnd - 1; return this; } private bool IsIndexValid(int index) { return index != -1; } private bool IsIndexInRange(int index) { if (index >= 0) { return index < instructions.Count; } return false; } public CodeInstruction GetRelativeInstruction(int offset) { if (!IsValid) { throw new InvalidOperationException("Injector is invalid"); } int num = index + offset; if (!IsIndexInRange(num)) { throw new IndexOutOfRangeException($"Offset {offset} would read out of bounds at index {num}"); } return instructions[num]; } public ILInjector SetRelativeInstruction(int offset, CodeInstruction instruction) { if (!IsValid) { throw new InvalidOperationException("Injector is invalid"); } int num = index + offset; if (!IsIndexInRange(num)) { throw new IndexOutOfRangeException($"Offset {offset} would write out of bounds at index {num}"); } instructions[num] = instruction; return this; } [IteratorStateMachine(typeof(d__34))] public IEnumerable GetRelativeInstructions(int offset, int size) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__34(-2) { <>4__this = this, <>3__offset = offset, <>3__size = size }; } public IEnumerable GetRelativeInstructions(int size) { return GetRelativeInstructions(0, size); } private void GetLastMatchRangeAbsolute(out int start, out int end) { start = index; end = matchEnd; if (start > end) { int num = end; int num2 = start; start = num; end = num2; } } private void GetLastMatchRange(out int start, out int size) { GetLastMatchRangeAbsolute(out start, out var end); if (start < 0 || start >= instructions.Count) { throw new InvalidOperationException($"Last match range starts at invalid index {start}"); } if (end < 0 || end > instructions.Count) { throw new InvalidOperationException($"Last match range ends at invalid index {end}"); } size = end - start; } public List GetLastMatch() { GetLastMatchRange(out var start, out var size); return instructions.GetRange(start, size); } public ILInjector DefineLabel(out Label label) { if (generator == null) { throw new InvalidOperationException("No ILGenerator was provided"); } label = generator.DefineLabel(); return this; } public ILInjector AddLabel(out Label label) { DefineLabel(out label); return AddLabel(label); } public ILInjector AddLabel(Label label) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown Instruction = new CodeInstruction(Instruction); Instruction.labels.Add(label); return this; } public ILInjector InsertInPlace(ICollection instructions) { if (!IsValid) { throw new InvalidOperationException("Injector is invalid"); } this.instructions.InsertRange(index, instructions); if (matchEnd >= index) { matchEnd += instructions.Count; } return this; } public ILInjector Insert(ICollection instructions) { InsertInPlace(instructions); index += instructions.Count; return this; } public ILInjector InsertInPlaceAfterBranch(ICollection instructions) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown if (!IsValid) { throw new InvalidOperationException("Injector is invalid"); } List