Decompiled source of Y4NGZUpgrades v1.0.0

Y4NGZUpgrades.dll

Decompiled 2 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using Dawn;
using DunGen;
using GameNetcodeStuff;
using HarmonyLib;
using LethalCompanyInputUtils.Api;
using LethalCompanyInputUtils.Config;
using LethalCompanyInputUtils.Data;
using Microsoft.CodeAnalysis;
using TMPro;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.Animations.Rigging;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.InputSystem.Utilities;
using UnityEngine.Networking;
using UnityEngine.Rendering;
using UnityEngine.Rendering.HighDefinition;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using Y4NGZInteractions.InteractionAnimationApi;
using Y4NGZUpgrades;
using Y4NGZUpgrades.Config;
using Y4NGZUpgrades.Effects;
using Y4NGZUpgrades.Gui;
using Y4NGZUpgrades.HUD;
using Y4NGZUpgrades.Interactive;
using Y4NGZUpgrades.Interactive.Feedback;
using Y4NGZUpgrades.Interactive.Hud;
using Y4NGZUpgrades.Interactive.Patches;
using Y4NGZUpgrades.Lucky8;
using Y4NGZUpgrades.Patches;
using Y4NGZUpgrades.UITheme;
using Y4NGZUpgrades.Upgrades;
using cakeslice;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("AmazingAssets.TerrainToMesh")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: IgnoresAccessChecksTo("ClientNetworkTransform")]
[assembly: IgnoresAccessChecksTo("com.olegknyazev.softmask")]
[assembly: IgnoresAccessChecksTo("DissonanceVoip")]
[assembly: IgnoresAccessChecksTo("DunGen")]
[assembly: IgnoresAccessChecksTo("DunGen.Integration.ASPP")]
[assembly: IgnoresAccessChecksTo("DunGen.Integration.UnityNav")]
[assembly: IgnoresAccessChecksTo("EasyTextEffects")]
[assembly: IgnoresAccessChecksTo("Facepunch Transport for Netcode for GameObjects")]
[assembly: IgnoresAccessChecksTo("Facepunch.Steamworks.Win64")]
[assembly: IgnoresAccessChecksTo("Unity.AI.Navigation")]
[assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging")]
[assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging.DocCodeExamples")]
[assembly: IgnoresAccessChecksTo("Unity.Burst")]
[assembly: IgnoresAccessChecksTo("Unity.Burst.Unsafe")]
[assembly: IgnoresAccessChecksTo("Unity.Collections")]
[assembly: IgnoresAccessChecksTo("Unity.Collections.LowLevel.ILSupport")]
[assembly: IgnoresAccessChecksTo("Unity.InputSystem")]
[assembly: IgnoresAccessChecksTo("Unity.InputSystem.ForUI")]
[assembly: IgnoresAccessChecksTo("Unity.Jobs")]
[assembly: IgnoresAccessChecksTo("Unity.Mathematics")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.Common")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.MetricTypes")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStats")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Component")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Configuration")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Implementation")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsReporting")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkProfiler.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkSolutionInterface")]
[assembly: IgnoresAccessChecksTo("Unity.Netcode.Components")]
[assembly: IgnoresAccessChecksTo("Unity.Netcode.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.Networking.Transport")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Csg")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.KdTree")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Poly2Tri")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Stl")]
[assembly: IgnoresAccessChecksTo("Unity.Profiling.Core")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.ShaderLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Config.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.ShaderGraph.ShaderGraphLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Authentication")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Analytics")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Components")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Configuration")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Device")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments.Internal")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Internal")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Networking")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Registration")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Scheduler")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Telemetry")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Threading")]
[assembly: IgnoresAccessChecksTo("Unity.Services.QoS")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Relay")]
[assembly: IgnoresAccessChecksTo("Unity.TextMeshPro")]
[assembly: IgnoresAccessChecksTo("Unity.Timeline")]
[assembly: IgnoresAccessChecksTo("Unity.VisualEffectGraph.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.XR.CoreUtils")]
[assembly: IgnoresAccessChecksTo("Unity.XR.Management")]
[assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR")]
[assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.ConformanceAutomation")]
[assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.MetaQuestSupport")]
[assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.MockRuntime")]
[assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.OculusQuestSupport")]
[assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.RuntimeDebugger")]
[assembly: IgnoresAccessChecksTo("UnityEngine.ARModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.NVIDIAModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.SpatialTracking")]
[assembly: IgnoresAccessChecksTo("UnityEngine.UI")]
[assembly: IgnoresAccessChecksTo("UnityEngine.XR.LegacyInputHelpers")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Y4NGZUpgrades")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Native Y4NGZ progression and upgrade framework spine")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+aa6e1cd1ef880d5a03be519cbac8a321e9211d53")]
[assembly: AssemblyProduct("Y4NGZUpgrades")]
[assembly: AssemblyTitle("Y4NGZUpgrades")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace cakeslice
{
	public sealed class LinkedSet<T> : IEnumerable<T>, IEnumerable
	{
		private readonly LinkedList<T> _list = new LinkedList<T>();

		private readonly Dictionary<T, LinkedListNode<T>> _dictionary = new Dictionary<T, LinkedListNode<T>>();

		public int Count => _list.Count;

		public bool Add(T item)
		{
			if (_dictionary.ContainsKey(item))
			{
				return false;
			}
			LinkedListNode<T> value = _list.AddLast(item);
			_dictionary.Add(item, value);
			return true;
		}

		public bool Remove(T item)
		{
			if (!_dictionary.TryGetValue(item, out var value))
			{
				return false;
			}
			_dictionary.Remove(item);
			_list.Remove(value);
			return true;
		}

		public bool Contains(T item)
		{
			return _dictionary.ContainsKey(item);
		}

		public LinkedList<T>.Enumerator GetEnumerator()
		{
			return _list.GetEnumerator();
		}

		IEnumerator<T> IEnumerable<T>.GetEnumerator()
		{
			return _list.GetEnumerator();
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return ((IEnumerable<T>)this).GetEnumerator();
		}
	}
	[RequireComponent(typeof(Renderer))]
	public sealed class Outline : MonoBehaviour
	{
		private static readonly Material[] EmptyMaterials = (Material[])(object)new Material[0];

		private Material[] _sharedMaterials;

		public int color;

		public bool eraseRenderer;

		public Renderer Renderer { get; private set; }

		public SpriteRenderer SpriteRenderer { get; private set; }

		public SkinnedMeshRenderer SkinnedMeshRenderer { get; private set; }

		public MeshFilter MeshFilter { get; private set; }

		public Material[] SharedMaterials
		{
			get
			{
				if (_sharedMaterials == null && (Object)(object)Renderer != (Object)null)
				{
					_sharedMaterials = Renderer.sharedMaterials;
				}
				return _sharedMaterials ?? EmptyMaterials;
			}
		}

		private void Awake()
		{
			Renderer = ((Component)this).GetComponent<Renderer>();
			SkinnedMeshRenderer = ((Component)this).GetComponent<SkinnedMeshRenderer>();
			SpriteRenderer = ((Component)this).GetComponent<SpriteRenderer>();
			MeshFilter = ((Component)this).GetComponent<MeshFilter>();
		}

		private void OnEnable()
		{
			OutlineEffect.Instance?.AddOutline(this);
		}

		private void OnDisable()
		{
			OutlineEffect.Instance?.RemoveOutline(this);
		}
	}
	[DisallowMultipleComponent]
	[RequireComponent(typeof(Camera))]
	public sealed class OutlineEffect : MonoBehaviour
	{
		public sealed class Y4NGZHDRPOutlinePass : CustomPass
		{
			internal OutlineEffect Owner;

			public override void Execute(CustomPassContext ctx)
			{
				//IL_0010: Unknown result type (might be due to invalid IL or missing references)
				//IL_0018: Unknown result type (might be due to invalid IL or missing references)
				//IL_0021: 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_0069: Unknown result type (might be due to invalid IL or missing references)
				//IL_0083: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e4: 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)
				OutlineEffect owner = Owner;
				if ((Object)(object)owner == (Object)null || ctx.cmd == null || ctx.hdCamera == null)
				{
					return;
				}
				Camera camera = ctx.hdCamera.camera;
				if ((Object)(object)camera == (Object)null || (Object)(object)camera != (Object)(object)owner.ResolveSourceCamera())
				{
					return;
				}
				if (!owner.HasActiveOutlines(out var activeOutlineCount))
				{
					owner.ResetHdrpCompositeTrace();
					return;
				}
				int width = Mathf.Max(1, ctx.hdCamera.actualWidth);
				int height = Mathf.Max(1, ctx.hdCamera.actualHeight);
				owner.sourceCamera = camera;
				if (!owner.RenderOutlineBuffer(ctx.cmd))
				{
					owner.ResetHdrpCompositeTrace();
					return;
				}
				if ((Object)(object)owner.outlineOverlayMaterial == (Object)null || (Object)(object)owner.renderTexture == (Object)null || !owner._outlineTextureValid)
				{
					owner.ResetHdrpCompositeTrace();
					return;
				}
				owner.outlineOverlayMaterial.SetTexture(OutlineSourceId, (Texture)(object)owner.renderTexture);
				HDUtils.DrawFullScreen(ctx.cmd, owner.outlineOverlayMaterial, ctx.cameraColorBuffer, ctx.cameraDepthBuffer, (MaterialPropertyBlock)null, 0);
				owner.TraceHdrpComposite(width, height, activeOutlineCount);
			}
		}

		private readonly LinkedSet<Outline> _outlines = new LinkedSet<Outline>();

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

		[Range(1f, 6f)]
		public float lineThickness = 1.25f;

		[Range(0f, 10f)]
		public float lineIntensity = 0.5f;

		[Range(0f, 1f)]
		public float fillAmount = 0.2f;

		public Color lineColor0 = Color.red;

		public Color lineColor1 = Color.green;

		public Color lineColor2 = Color.blue;

		public bool additiveRendering;

		public bool backfaceCulling = true;

		public Color fillColor = Color.blue;

		public bool useFillColor;

		public bool cornerOutlines;

		public bool addLinesBetweenColors;

		public bool scaleWithScreenSize = true;

		[Range(0f, 1f)]
		public float alphaCutoff = 0.5f;

		public bool flipY;

		public Camera sourceCamera;

		public bool autoEnableOutlines;

		public Camera outlineCamera;

		public Material outlineShaderMaterial;

		private Material outlineOverlayMaterial;

		public RenderTexture renderTexture;

		public RenderTexture extraRenderTexture;

		private Material _outline1Material;

		private Material _outline2Material;

		private Material _outline3Material;

		private Material _outlineEraseMaterial;

		private Material _fallback1Material;

		private Material _fallback2Material;

		private Material _fallback3Material;

		private Shader _outlineShader;

		private Shader _outlineBufferShader;

		private Shader _outlineOverlayShader;

		private Shader _maskShader;

		private CommandBuffer _immediateCommandBuffer;

		private GameObject _customPassVolumeObject;

		private CustomPassVolume _customPassVolume;

		private Y4NGZHDRPOutlinePass _customPass;

		private bool _renderNextFrame;

		private bool _pipelineCallbacksRegistered;

		private bool _outlineTextureValid;

		private float _nextFallbackWarningAt;

		private float _nextHdrpWarningAt;

		private bool _hdrpTraceActive;

		private int _lastHdrpTraceActiveCount = int.MinValue;

		private int _lastHdrpTraceWidth;

		private int _lastHdrpTraceHeight;

		private static readonly int CompositeTempId = Shader.PropertyToID("_Y4NGZOutlineCompositeTemp");

		private static readonly int OutlineSourceId = Shader.PropertyToID("_OutlineSource");

		private static readonly string[] MaskPassNames = new string[4] { "ForwardOnly", "Forward", "SRPDefaultUnlit", "DepthForwardOnly" };

		public static OutlineEffect Instance { get; private set; }

		private void Awake()
		{
			if ((Object)(object)Instance != (Object)null && (Object)(object)Instance != (Object)(object)this)
			{
				Object.Destroy((Object)(object)Instance);
			}
			Instance = this;
		}

		private void Start()
		{
			CreateMaterialsIfNeeded();
			UpdateMaterialsPublicProperties();
			if ((Object)(object)sourceCamera == (Object)null)
			{
				sourceCamera = ((Component)this).GetComponent<Camera>() ?? Camera.main;
			}
			RecreateRenderTexturesIfNeeded();
			EnsureHdrpCustomPass();
		}

		private void OnEnable()
		{
			if ((Object)(object)GraphicsSettings.currentRenderPipeline != (Object)null)
			{
				EnsureHdrpCustomPass();
			}
			else
			{
				RegisterPipelineCallbacks();
			}
			Outline[] array = Object.FindObjectsOfType<Outline>();
			for (int i = 0; i < array.Length; i++)
			{
				if ((Object)(object)array[i] != (Object)null && !_outlines.Contains(array[i]))
				{
					_outlines.Add(array[i]);
				}
			}
		}

		private void OnDisable()
		{
			UnregisterPipelineCallbacks();
			if ((Object)(object)_customPassVolume != (Object)null)
			{
				((Behaviour)_customPassVolume).enabled = false;
			}
			ResetHdrpCompositeTrace();
		}

		private void OnPreRender()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			if (!((Object)(object)GraphicsSettings.currentRenderPipeline != (Object)null))
			{
				if (_immediateCommandBuffer == null)
				{
					_immediateCommandBuffer = new CommandBuffer
					{
						name = "Y4NGZ Outline Buffer"
					};
				}
				_immediateCommandBuffer.Clear();
				if (RenderOutlineBuffer(_immediateCommandBuffer))
				{
					Graphics.ExecuteCommandBuffer(_immediateCommandBuffer);
				}
			}
		}

		[ImageEffectOpaque]
		private void OnRenderImage(RenderTexture source, RenderTexture destination)
		{
			if ((Object)(object)outlineShaderMaterial == (Object)null || (Object)(object)renderTexture == (Object)null || !_outlineTextureValid)
			{
				Graphics.Blit((Texture)(object)source, destination);
				return;
			}
			outlineShaderMaterial.SetTexture("_OutlineSource", (Texture)(object)renderTexture);
			if (addLinesBetweenColors && (Object)(object)extraRenderTexture != (Object)null)
			{
				Graphics.Blit((Texture)(object)source, extraRenderTexture, outlineShaderMaterial, 0);
				outlineShaderMaterial.SetTexture("_OutlineSource", (Texture)(object)extraRenderTexture);
			}
			Graphics.Blit((Texture)(object)source, destination, outlineShaderMaterial, 1);
		}

		private void OnDestroy()
		{
			if ((Object)(object)Instance == (Object)(object)this)
			{
				Instance = null;
			}
			UnregisterPipelineCallbacks();
			if ((Object)(object)_customPassVolumeObject != (Object)null)
			{
				Object.Destroy((Object)(object)_customPassVolumeObject);
				_customPassVolumeObject = null;
				_customPassVolume = null;
				_customPass = null;
			}
			if (_immediateCommandBuffer != null)
			{
				_immediateCommandBuffer.Release();
				_immediateCommandBuffer = null;
			}
			if ((Object)(object)renderTexture != (Object)null)
			{
				renderTexture.Release();
			}
			if ((Object)(object)extraRenderTexture != (Object)null)
			{
				extraRenderTexture.Release();
			}
			DestroyMaterials();
		}

		public void AddOutline(Outline outline)
		{
			if (!((Object)(object)outline == (Object)null))
			{
				_outlines.Add(outline);
				EnsureHdrpCustomPass();
			}
		}

		public void RemoveOutline(Outline outline)
		{
			if ((Object)(object)outline != (Object)null)
			{
				_outlines.Remove(outline);
			}
		}

		private bool HasActiveOutlines(out int activeOutlineCount)
		{
			activeOutlineCount = 0;
			if (_outlines.Count == 0)
			{
				return false;
			}
			foreach (Outline outline in _outlines)
			{
				if ((Object)(object)outline != (Object)null && ((Behaviour)outline).enabled && (Object)(object)outline.Renderer != (Object)null && outline.Renderer.enabled)
				{
					activeOutlineCount++;
				}
			}
			return activeOutlineCount > 0;
		}

		private void EnsureHdrpCustomPass()
		{
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Expected O, but got Unknown
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)GraphicsSettings.currentRenderPipeline == (Object)null)
			{
				return;
			}
			Camera val = ResolveSourceCamera();
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			if ((Object)(object)_customPassVolume != (Object)null && _customPass != null)
			{
				_customPass.Owner = this;
				_customPassVolume.targetCamera = val;
				((Behaviour)_customPassVolume).enabled = ((Behaviour)this).isActiveAndEnabled;
				return;
			}
			if ((Object)(object)_customPassVolumeObject == (Object)null)
			{
				_customPassVolumeObject = new GameObject("Y4NGZ_OutlineCustomPassVolume")
				{
					hideFlags = (HideFlags)61
				};
				Object.DontDestroyOnLoad((Object)(object)_customPassVolumeObject);
			}
			_customPassVolume = _customPassVolumeObject.GetComponent<CustomPassVolume>();
			if ((Object)(object)_customPassVolume == (Object)null)
			{
				_customPassVolume = _customPassVolumeObject.AddComponent<CustomPassVolume>();
			}
			_customPassVolume.isGlobal = true;
			_customPassVolume.priority = 1000f;
			_customPassVolume.injectionPoint = (CustomPassInjectionPoint)3;
			_customPassVolume.targetCamera = val;
			_customPassVolume.customPasses.Clear();
			CustomPass val2 = _customPassVolume.AddPassOfType(typeof(Y4NGZHDRPOutlinePass));
			_customPass = val2 as Y4NGZHDRPOutlinePass;
			if (_customPass == null)
			{
				if (Time.unscaledTime >= _nextHdrpWarningAt)
				{
					_nextHdrpWarningAt = Time.unscaledTime + 10f;
					ManualLogSource log = Y4NGZUpgrades.Plugin.Log;
					if (log != null)
					{
						log.LogWarning((object)"OutlineEffect: failed to register HDRP custom pass; outlines may be invisible.");
					}
				}
				return;
			}
			((CustomPass)_customPass).name = "Y4NGZ Outline Composite";
			((CustomPass)_customPass).enabled = true;
			((CustomPass)_customPass).targetColorBuffer = (TargetBuffer)0;
			((CustomPass)_customPass).targetDepthBuffer = (TargetBuffer)0;
			((CustomPass)_customPass).clearFlags = (ClearFlag)0;
			_customPass.Owner = this;
			((Behaviour)_customPassVolume).enabled = ((Behaviour)this).isActiveAndEnabled;
			ManualLogSource log2 = Y4NGZUpgrades.Plugin.Log;
			if (log2 != null)
			{
				log2.LogInfo((object)("OutlineEffect: HDRP custom pass registered on '" + ((Object)val).name + "'."));
			}
		}

		private void TraceHdrpComposite(int width, int height, int activeOutlineCount)
		{
			if (!_hdrpTraceActive || _lastHdrpTraceActiveCount != activeOutlineCount || _lastHdrpTraceWidth != width || _lastHdrpTraceHeight != height)
			{
				_hdrpTraceActive = true;
				_lastHdrpTraceActiveCount = activeOutlineCount;
				_lastHdrpTraceWidth = width;
				_lastHdrpTraceHeight = height;
				ManualLogSource log = Y4NGZUpgrades.Plugin.Log;
				if (log != null)
				{
					log.LogDebug((object)$"OutlineEffect: HDRP custom pass compositing {activeOutlineCount} outline renderer(s) at {width}x{height}.");
				}
			}
		}

		private void ResetHdrpCompositeTrace()
		{
			_hdrpTraceActive = false;
			_lastHdrpTraceActiveCount = int.MinValue;
			_lastHdrpTraceWidth = 0;
			_lastHdrpTraceHeight = 0;
		}

		public void UpdateMaterialsPublicProperties()
		{
			if (CreateMaterialsIfNeeded() && !((Object)(object)outlineShaderMaterial == (Object)null))
			{
				float num = 1f;
				if (scaleWithScreenSize)
				{
					num = (float)Screen.height / 360f;
				}
				float thicknessScale = ((scaleWithScreenSize && num >= 1f) ? num : 1f);
				ApplyMaterialProperties(outlineShaderMaterial, thicknessScale, legacyComposite: true);
				if ((Object)(object)outlineOverlayMaterial != (Object)null)
				{
					ApplyMaterialProperties(outlineOverlayMaterial, thicknessScale, legacyComposite: false);
				}
				Shader.SetGlobalFloat("_OutlineAlphaCutoff", alphaCutoff);
			}
		}

		private void ApplyMaterialProperties(Material material, float thicknessScale, bool legacyComposite)
		{
			//IL_0075: 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_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: 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)
			if (!((Object)(object)material == (Object)null))
			{
				material.SetFloat("_LineThicknessX", thicknessScale * (lineThickness / Mathf.Max(1f, (float)Screen.width)));
				material.SetFloat("_LineThicknessY", thicknessScale * (lineThickness / Mathf.Max(1f, (float)Screen.height)));
				material.SetFloat("_LineIntensity", lineIntensity);
				material.SetColor("_LineColor1", legacyComposite ? (lineColor0 * lineColor0) : lineColor0);
				material.SetColor("_LineColor2", legacyComposite ? (lineColor1 * lineColor1) : lineColor1);
				material.SetColor("_LineColor3", legacyComposite ? (lineColor2 * lineColor2) : lineColor2);
				material.SetInt("_CornerOutlines", cornerOutlines ? 1 : 0);
				if (legacyComposite)
				{
					material.SetFloat("_FillAmount", fillAmount);
					material.SetColor("_FillColor", fillColor);
					material.SetFloat("_UseFillColor", useFillColor ? 1f : 0f);
					material.SetInt("_FlipY", flipY ? 1 : 0);
					material.SetInt("_Dark", (!additiveRendering) ? 1 : 0);
				}
			}
		}

		private void OnBeginCameraRendering(ScriptableRenderContext context, Camera camera)
		{
			if ((Object)(object)GraphicsSettings.currentRenderPipeline != (Object)null || (Object)(object)camera == (Object)null || (Object)(object)camera != (Object)(object)ResolveSourceCamera())
			{
				return;
			}
			CommandBuffer val = CommandBufferPool.Get("Y4NGZ Outline Buffer");
			try
			{
				if (RenderOutlineBuffer(val))
				{
					((ScriptableRenderContext)(ref context)).ExecuteCommandBuffer(val);
				}
			}
			finally
			{
				CommandBufferPool.Release(val);
			}
		}

		private void OnEndCameraRendering(ScriptableRenderContext context, Camera camera)
		{
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)GraphicsSettings.currentRenderPipeline != (Object)null || (Object)(object)camera == (Object)null || (Object)(object)camera != (Object)(object)ResolveSourceCamera() || (Object)(object)outlineShaderMaterial == (Object)null || (Object)(object)renderTexture == (Object)null || !_outlineTextureValid)
			{
				return;
			}
			int num = Mathf.Max(1, camera.pixelWidth);
			int num2 = Mathf.Max(1, camera.pixelHeight);
			CommandBuffer val = CommandBufferPool.Get("Y4NGZ Outline Composite");
			try
			{
				outlineShaderMaterial.SetTexture("_OutlineSource", (Texture)(object)renderTexture);
				val.GetTemporaryRT(CompositeTempId, num, num2, 0, (FilterMode)1, (RenderTextureFormat)7);
				val.Blit(RenderTargetIdentifier.op_Implicit((BuiltinRenderTextureType)2), RenderTargetIdentifier.op_Implicit(CompositeTempId), outlineShaderMaterial, 1);
				val.Blit(RenderTargetIdentifier.op_Implicit(CompositeTempId), RenderTargetIdentifier.op_Implicit((BuiltinRenderTextureType)2));
				val.ReleaseTemporaryRT(CompositeTempId);
				((ScriptableRenderContext)(ref context)).ExecuteCommandBuffer(val);
			}
			finally
			{
				CommandBufferPool.Release(val);
			}
		}

		private void DrawFallbackSilhouettes(ScriptableRenderContext context, Camera camera)
		{
			if ((Object)(object)camera == (Object)null || (Object)(object)camera != (Object)(object)ResolveSourceCamera())
			{
				return;
			}
			CommandBuffer val = CommandBufferPool.Get("Y4NGZ Outline Fallback");
			try
			{
				DrawFallbackSilhouettes(val);
				((ScriptableRenderContext)(ref context)).ExecuteCommandBuffer(val);
			}
			finally
			{
				CommandBufferPool.Release(val);
			}
		}

		private void DrawImmediateFallback()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			if (_outlines.Count != 0)
			{
				if (_immediateCommandBuffer == null)
				{
					_immediateCommandBuffer = new CommandBuffer
					{
						name = "Y4NGZ Outline Buffer"
					};
				}
				_immediateCommandBuffer.Clear();
				DrawFallbackSilhouettes(_immediateCommandBuffer);
				Graphics.ExecuteCommandBuffer(_immediateCommandBuffer);
			}
		}

		private bool RenderOutlineBuffer(CommandBuffer commandBuffer)
		{
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			if (commandBuffer == null)
			{
				return false;
			}
			if ((Object)(object)ResolveSourceCamera() == (Object)null)
			{
				return false;
			}
			if (_outlines.Count == 0)
			{
				if (!_renderNextFrame)
				{
					return false;
				}
				_renderNextFrame = false;
			}
			else
			{
				_renderNextFrame = true;
			}
			if (!CreateMaterialsIfNeeded())
			{
				return false;
			}
			RecreateRenderTexturesIfNeeded();
			UpdateMaterialsPublicProperties();
			if ((Object)(object)renderTexture == (Object)null)
			{
				return false;
			}
			commandBuffer.SetRenderTarget(RenderTargetIdentifier.op_Implicit((Texture)(object)renderTexture));
			commandBuffer.SetViewport(new Rect(0f, 0f, (float)((Texture)renderTexture).width, (float)((Texture)renderTexture).height));
			commandBuffer.ClearRenderTarget(true, true, Color.clear);
			commandBuffer.SetViewProjectionMatrices(sourceCamera.worldToCameraMatrix, sourceCamera.projectionMatrix);
			foreach (Outline outline in _outlines)
			{
				DrawOutline(commandBuffer, outline);
			}
			_outlineTextureValid = true;
			return true;
		}

		private Camera ResolveSourceCamera()
		{
			if ((Object)(object)sourceCamera == (Object)null)
			{
				sourceCamera = ((Component)this).GetComponent<Camera>() ?? Camera.main;
			}
			return sourceCamera;
		}

		private void RegisterPipelineCallbacks()
		{
			if (!_pipelineCallbacksRegistered)
			{
				RenderPipelineManager.beginCameraRendering += OnBeginCameraRendering;
				RenderPipelineManager.endCameraRendering += OnEndCameraRendering;
				_pipelineCallbacksRegistered = true;
			}
		}

		private void UnregisterPipelineCallbacks()
		{
			if (_pipelineCallbacksRegistered)
			{
				RenderPipelineManager.beginCameraRendering -= OnBeginCameraRendering;
				RenderPipelineManager.endCameraRendering -= OnEndCameraRendering;
				_pipelineCallbacksRegistered = false;
			}
		}

		private void DrawOutline(CommandBuffer commandBuffer, Outline outline)
		{
			if ((Object)(object)outline == (Object)null || (Object)(object)outline.Renderer == (Object)null || !((Behaviour)outline).enabled)
			{
				return;
			}
			Material[] sharedMaterials = outline.SharedMaterials;
			for (int i = 0; i < sharedMaterials.Length; i++)
			{
				Material val = ResolveBufferMaterial(outline, sharedMaterials[i]);
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				if (val.HasProperty("_Culling"))
				{
					val.SetInt("_Culling", backfaceCulling ? 2 : 0);
				}
				if (val.HasProperty("_Cull"))
				{
					val.SetInt("_Cull", backfaceCulling ? 2 : 0);
				}
				MeshFilter meshFilter = outline.MeshFilter;
				SkinnedMeshRenderer skinnedMeshRenderer = outline.SkinnedMeshRenderer;
				SpriteRenderer spriteRenderer = outline.SpriteRenderer;
				int num = ResolveMaskMaterialPass(val);
				if ((Object)(object)meshFilter != (Object)null && (Object)(object)meshFilter.sharedMesh != (Object)null)
				{
					if (i < meshFilter.sharedMesh.subMeshCount)
					{
						commandBuffer.DrawRenderer(outline.Renderer, val, i, num);
					}
				}
				else if ((Object)(object)skinnedMeshRenderer != (Object)null && (Object)(object)skinnedMeshRenderer.sharedMesh != (Object)null)
				{
					if (i < skinnedMeshRenderer.sharedMesh.subMeshCount)
					{
						commandBuffer.DrawRenderer(outline.Renderer, val, i, num);
					}
				}
				else if ((Object)(object)spriteRenderer != (Object)null)
				{
					commandBuffer.DrawRenderer(outline.Renderer, val, i, num);
				}
			}
		}

		private void DrawFallbackSilhouettes(CommandBuffer commandBuffer)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			if (commandBuffer == null || _outlines.Count == 0 || !CreateFallbackMaterialsIfNeeded())
			{
				return;
			}
			commandBuffer.SetRenderTarget(RenderTargetIdentifier.op_Implicit((BuiltinRenderTextureType)2));
			foreach (Outline outline in _outlines)
			{
				DrawFallbackSilhouette(commandBuffer, outline);
			}
		}

		private void DrawFallbackSilhouettes(CommandBuffer commandBuffer, RTHandle colorBuffer, RTHandle depthBuffer)
		{
			if (commandBuffer == null || colorBuffer == null || _outlines.Count == 0 || !CreateFallbackMaterialsIfNeeded())
			{
				return;
			}
			CoreUtils.SetRenderTarget(commandBuffer, colorBuffer, depthBuffer, (ClearFlag)0, 0, (CubemapFace)(-1), -1);
			foreach (Outline outline in _outlines)
			{
				DrawFallbackSilhouette(commandBuffer, outline);
			}
		}

		private void DrawFallbackSilhouette(CommandBuffer commandBuffer, Outline outline)
		{
			if ((Object)(object)outline == (Object)null || (Object)(object)outline.Renderer == (Object)null || !((Behaviour)outline).enabled)
			{
				return;
			}
			Material fallbackMaterialFromId = GetFallbackMaterialFromId(outline.color);
			if (!((Object)(object)fallbackMaterialFromId == (Object)null))
			{
				Material[] sharedMaterials = outline.SharedMaterials;
				int num = ResolveMaskMaterialPass(fallbackMaterialFromId);
				for (int i = 0; i < sharedMaterials.Length; i++)
				{
					commandBuffer.DrawRenderer(outline.Renderer, fallbackMaterialFromId, i, num);
				}
			}
		}

		private Material ResolveBufferMaterial(Outline outline, Material sourceMaterial)
		{
			if ((Object)(object)outline == (Object)null)
			{
				return null;
			}
			if (!outline.eraseRenderer)
			{
				return GetMaterialFromId(outline.color);
			}
			return _outlineEraseMaterial;
		}

		private Material GetMaterialFromId(int id)
		{
			return (Material)(id switch
			{
				1 => _outline2Material, 
				2 => _outline3Material, 
				_ => _outline1Material, 
			});
		}

		private Material GetFallbackMaterialFromId(int id)
		{
			return (Material)(id switch
			{
				1 => _fallback2Material, 
				2 => _fallback3Material, 
				_ => _fallback1Material, 
			});
		}

		private void EnsureOutlineCamera()
		{
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Expected O, but got Unknown
			if ((Object)(object)sourceCamera == (Object)null || (Object)(object)outlineCamera != (Object)null)
			{
				return;
			}
			Camera[] componentsInChildren = ((Component)this).GetComponentsInChildren<Camera>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if ((Object)(object)componentsInChildren[i] != (Object)null && ((Object)componentsInChildren[i]).name == "Outline Camera")
				{
					outlineCamera = componentsInChildren[i];
					((Behaviour)outlineCamera).enabled = false;
					return;
				}
			}
			GameObject val = new GameObject("Outline Camera");
			val.transform.SetParent(((Component)sourceCamera).transform, false);
			outlineCamera = val.AddComponent<Camera>();
			((Behaviour)outlineCamera).enabled = false;
		}

		private void RecreateRenderTexturesIfNeeded()
		{
			//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_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Expected O, but got Unknown
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Expected O, but got Unknown
			if ((Object)(object)sourceCamera == (Object)null)
			{
				return;
			}
			int num = Mathf.Max(1, sourceCamera.pixelWidth);
			int num2 = Mathf.Max(1, sourceCamera.pixelHeight);
			if ((Object)(object)renderTexture == (Object)null || ((Texture)renderTexture).width != num || ((Texture)renderTexture).height != num2)
			{
				if ((Object)(object)renderTexture != (Object)null)
				{
					renderTexture.Release();
				}
				if ((Object)(object)extraRenderTexture != (Object)null)
				{
					extraRenderTexture.Release();
				}
				_outlineTextureValid = false;
				renderTexture = new RenderTexture(num, num2, 16, (RenderTextureFormat)0)
				{
					filterMode = (FilterMode)0,
					wrapMode = (TextureWrapMode)1
				};
				extraRenderTexture = new RenderTexture(num, num2, 16, (RenderTextureFormat)0)
				{
					filterMode = (FilterMode)0,
					wrapMode = (TextureWrapMode)1
				};
				if ((Object)(object)outlineCamera != (Object)null)
				{
					outlineCamera.targetTexture = renderTexture;
				}
			}
		}

		private bool CreateMaterialsIfNeeded()
		{
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Expected O, but got Unknown
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Expected O, but got Unknown
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_outlineShader == (Object)null)
			{
				_outlineShader = OutlineRuntimeAssets.LoadShader("OutlineShader");
			}
			if ((Object)(object)_outlineBufferShader == (Object)null)
			{
				_outlineBufferShader = OutlineRuntimeAssets.LoadShader("OutlineBufferShader");
			}
			if ((Object)(object)_outlineOverlayShader == (Object)null)
			{
				_outlineOverlayShader = OutlineRuntimeAssets.LoadShader("Y4NGZOutlineOverlayShader");
			}
			if ((Object)(object)_outlineShader == (Object)null)
			{
				return false;
			}
			if ((Object)(object)GraphicsSettings.currentRenderPipeline != (Object)null && (Object)(object)_outlineOverlayShader == (Object)null)
			{
				return false;
			}
			if ((Object)(object)outlineShaderMaterial == (Object)null)
			{
				outlineShaderMaterial = new Material(_outlineShader)
				{
					hideFlags = (HideFlags)61
				};
			}
			if ((Object)(object)outlineOverlayMaterial == (Object)null && (Object)(object)_outlineOverlayShader != (Object)null)
			{
				outlineOverlayMaterial = new Material(_outlineOverlayShader)
				{
					hideFlags = (HideFlags)61
				};
			}
			if ((Object)(object)_outlineEraseMaterial == (Object)null)
			{
				_outlineEraseMaterial = CreateMaterial(new Color(0f, 0f, 0f, 0f));
			}
			if ((Object)(object)_outline1Material == (Object)null)
			{
				_outline1Material = CreateMaterial(new Color(1f, 0f, 0f, 1f));
			}
			if ((Object)(object)_outline2Material == (Object)null)
			{
				_outline2Material = CreateMaterial(new Color(0f, 1f, 0f, 1f));
			}
			if ((Object)(object)_outline3Material == (Object)null)
			{
				_outline3Material = CreateMaterial(new Color(0f, 0f, 1f, 1f));
			}
			if ((Object)(object)outlineShaderMaterial != (Object)null && ((Object)(object)GraphicsSettings.currentRenderPipeline == (Object)null || (Object)(object)outlineOverlayMaterial != (Object)null) && (Object)(object)_outlineEraseMaterial != (Object)null && (Object)(object)_outline1Material != (Object)null && (Object)(object)_outline2Material != (Object)null)
			{
				return (Object)(object)_outline3Material != (Object)null;
			}
			return false;
		}

		private bool CreateFallbackMaterialsIfNeeded()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_fallback1Material == (Object)null)
			{
				_fallback1Material = CreateFallbackMaterial(lineColor0);
			}
			if ((Object)(object)_fallback2Material == (Object)null)
			{
				_fallback2Material = CreateFallbackMaterial(lineColor1);
			}
			if ((Object)(object)_fallback3Material == (Object)null)
			{
				_fallback3Material = CreateFallbackMaterial(lineColor2);
			}
			if ((Object)(object)_fallback1Material != (Object)null && (Object)(object)_fallback2Material != (Object)null)
			{
				return (Object)(object)_fallback3Material != (Object)null;
			}
			return false;
		}

		private Material CreateMaterial(Color emissionColor)
		{
			//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)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			//IL_0033: Expected O, but got Unknown
			Shader val = ResolveMaskShader();
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			Material val2 = new Material(val)
			{
				hideFlags = (HideFlags)61,
				renderQueue = 2500
			};
			ConfigureMaskMaterial(val2, emissionColor);
			return val2;
		}

		private Shader ResolveMaskShader()
		{
			if ((Object)(object)_maskShader != (Object)null)
			{
				return _maskShader;
			}
			if ((Object)(object)GraphicsSettings.currentRenderPipeline != (Object)null)
			{
				_maskShader = Shader.Find("HDRP/Unlit") ?? Shader.Find("Hidden/Internal-Colored") ?? Shader.Find("Unlit/Color");
			}
			if ((Object)(object)_maskShader == (Object)null)
			{
				_maskShader = _outlineBufferShader;
			}
			return _maskShader;
		}

		private static void ConfigureMaskMaterial(Material material, Color color)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)material == (Object)null))
			{
				SetColorIfPresent(material, "_Color", color);
				SetColorIfPresent(material, "_BaseColor", color);
				SetColorIfPresent(material, "_UnlitColor", color);
				SetColorIfPresent(material, "_EmissiveColor", color);
				SetFloatIfPresent(material, "_SurfaceType", 0f);
				SetFloatIfPresent(material, "_AlphaCutoffEnable", 0f);
				SetFloatIfPresent(material, "_ZWrite", 0f);
				SetFloatIfPresent(material, "_ZTestDepthEqualForOpaque", 8f);
				SetIntIfPresent(material, "_SrcBlend", 1);
				SetIntIfPresent(material, "_DstBlend", 0);
				SetIntIfPresent(material, "_Cull", 0);
				SetIntIfPresent(material, "_Culling", 0);
				material.DisableKeyword("_ALPHATEST_ON");
				material.DisableKeyword("_ALPHABLEND_ON");
				material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
			}
		}

		private static int ResolveMaskMaterialPass(Material material)
		{
			if ((Object)(object)material == (Object)null)
			{
				return 0;
			}
			for (int i = 0; i < MaskPassNames.Length; i++)
			{
				int num = material.FindPass(MaskPassNames[i]);
				if (num >= 0)
				{
					return num;
				}
			}
			return 0;
		}

		private static void SetColorIfPresent(Material material, string name, Color value)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			if (material.HasProperty(name))
			{
				material.SetColor(name, value);
			}
		}

		private static void SetFloatIfPresent(Material material, string name, float value)
		{
			if (material.HasProperty(name))
			{
				material.SetFloat(name, value);
			}
		}

		private static void SetIntIfPresent(Material material, string name, int value)
		{
			if (material.HasProperty(name))
			{
				material.SetInt(name, value);
			}
		}

		private Material CreateFallbackMaterial(Color color)
		{
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Expected O, but got Unknown
			//IL_00ac: Expected O, but got Unknown
			Shader val = (((Object)(object)GraphicsSettings.currentRenderPipeline != (Object)null) ? (Shader.Find("HDRP/Unlit") ?? Shader.Find("Hidden/Internal-Colored")) : Shader.Find("Hidden/Internal-Colored"));
			if ((Object)(object)val == (Object)null)
			{
				if (Time.unscaledTime >= _nextFallbackWarningAt)
				{
					_nextFallbackWarningAt = Time.unscaledTime + 10f;
					ManualLogSource log = Y4NGZUpgrades.Plugin.Log;
					if (log != null)
					{
						log.LogWarning((object)"OutlineEffect: Hidden/Internal-Colored shader unavailable; through-wall fallback silhouettes disabled.");
					}
				}
				return null;
			}
			Material val2 = new Material(val)
			{
				hideFlags = (HideFlags)61,
				renderQueue = 5000
			};
			ConfigureOverlayMaterial(val2, new Color(color.r, color.g, color.b, 0.32f));
			return val2;
		}

		private static void ConfigureOverlayMaterial(Material material, Color color)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)material == (Object)null))
			{
				SetColorIfPresent(material, "_Color", color);
				SetColorIfPresent(material, "_BaseColor", color);
				SetColorIfPresent(material, "_UnlitColor", color);
				SetColorIfPresent(material, "_EmissiveColor", color);
				SetFloatIfPresent(material, "_SurfaceType", 1f);
				SetFloatIfPresent(material, "_BlendMode", 0f);
				SetFloatIfPresent(material, "_AlphaCutoffEnable", 0f);
				SetFloatIfPresent(material, "_ZWrite", 0f);
				SetFloatIfPresent(material, "_TransparentZWrite", 0f);
				SetFloatIfPresent(material, "_ZTest", 8f);
				SetFloatIfPresent(material, "_ZTestTransparent", 8f);
				SetFloatIfPresent(material, "_ZTestDepthEqualForOpaque", 8f);
				SetIntIfPresent(material, "_SrcBlend", 5);
				SetIntIfPresent(material, "_DstBlend", 10);
				SetIntIfPresent(material, "_AlphaSrcBlend", 1);
				SetIntIfPresent(material, "_AlphaDstBlend", 10);
				SetIntIfPresent(material, "_Cull", 0);
				SetIntIfPresent(material, "_CullMode", 0);
				SetIntIfPresent(material, "_CullModeForward", 0);
				material.EnableKeyword("_SURFACE_TYPE_TRANSPARENT");
				material.EnableKeyword("_BLENDMODE_ALPHA");
				material.DisableKeyword("_ALPHATEST_ON");
				material.EnableKeyword("_ALPHABLEND_ON");
				material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
			}
		}

		private void UpdateOutlineCameraFromSource()
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)outlineCamera == (Object)null) && !((Object)(object)sourceCamera == (Object)null))
			{
				outlineCamera.CopyFrom(sourceCamera);
				outlineCamera.renderingPath = (RenderingPath)1;
				outlineCamera.backgroundColor = new Color(0f, 0f, 0f, 0f);
				outlineCamera.clearFlags = (CameraClearFlags)2;
				outlineCamera.rect = new Rect(0f, 0f, 1f, 1f);
				outlineCamera.cullingMask = 0;
				outlineCamera.targetTexture = renderTexture;
				((Behaviour)outlineCamera).enabled = false;
				outlineCamera.allowHDR = false;
			}
		}

		private void DestroyMaterials()
		{
			for (int i = 0; i < _materialBuffer.Count; i++)
			{
				if ((Object)(object)_materialBuffer[i] != (Object)null)
				{
					Object.Destroy((Object)(object)_materialBuffer[i]);
				}
			}
			_materialBuffer.Clear();
			if ((Object)(object)outlineShaderMaterial != (Object)null)
			{
				Object.Destroy((Object)(object)outlineShaderMaterial);
			}
			if ((Object)(object)outlineOverlayMaterial != (Object)null)
			{
				Object.Destroy((Object)(object)outlineOverlayMaterial);
			}
			if ((Object)(object)_outlineEraseMaterial != (Object)null)
			{
				Object.Destroy((Object)(object)_outlineEraseMaterial);
			}
			if ((Object)(object)_outline1Material != (Object)null)
			{
				Object.Destroy((Object)(object)_outline1Material);
			}
			if ((Object)(object)_outline2Material != (Object)null)
			{
				Object.Destroy((Object)(object)_outline2Material);
			}
			if ((Object)(object)_outline3Material != (Object)null)
			{
				Object.Destroy((Object)(object)_outline3Material);
			}
			if ((Object)(object)_fallback1Material != (Object)null)
			{
				Object.Destroy((Object)(object)_fallback1Material);
			}
			if ((Object)(object)_fallback2Material != (Object)null)
			{
				Object.Destroy((Object)(object)_fallback2Material);
			}
			if ((Object)(object)_fallback3Material != (Object)null)
			{
				Object.Destroy((Object)(object)_fallback3Material);
			}
		}
	}
}
namespace Y4NGZUpgrades
{
	internal static class ArmoryBridge
	{
		private const string ArmoryPluginGuid = "com.y4ngz.betterarmory";

		private const string PrizeApiTypeName = "Y4NGZUpgrades.Weapons.ArmoryPrizeApi";

		private const string AmmoApiTypeName = "Y4NGZUpgrades.Weapons.ArmoryAmmoReserveApi";

		private const string PresentationApiTypeName = "Y4NGZUpgrades.Weapons.ArmoryPresentationApi";

		private static readonly string[] NoIds = new string[0];

		private static readonly Type[] OneString = new Type[1] { typeof(string) };

		private static bool _presenceResolved;

		private static bool _present;

		private static readonly Lazy<MethodInfo> WeaponPrizeIds = Method("Y4NGZUpgrades.Weapons.ArmoryPrizeApi", "GetWeaponPrizeIds", Type.EmptyTypes);

		private static readonly Lazy<MethodInfo> WeaponDisplayName = Method("Y4NGZUpgrades.Weapons.ArmoryPrizeApi", "GetWeaponDisplayName", OneString);

		private static readonly Lazy<MethodInfo> WeaponPrizePrefab = Method("Y4NGZUpgrades.Weapons.ArmoryPrizeApi", "GetWeaponPrizePrefab", OneString);

		private static readonly Lazy<MethodInfo> WeaponItem = Method("Y4NGZUpgrades.Weapons.ArmoryPrizeApi", "GetWeaponItem", OneString);

		private static readonly Lazy<MethodInfo> WeaponFingerprint = Method("Y4NGZUpgrades.Weapons.ArmoryPrizeApi", "GetWeaponFingerprintTokens", Type.EmptyTypes);

		private static readonly Lazy<MethodInfo> WeaponPrizeInit = Method("Y4NGZUpgrades.Weapons.ArmoryPrizeApi", "InitializeWeaponPrize", new Type[2]
		{
			typeof(GameObject),
			typeof(string)
		});

		private static readonly Lazy<MethodInfo> AmmoPrizeIds = Method("Y4NGZUpgrades.Weapons.ArmoryPrizeApi", "GetAmmoPrizeIds", Type.EmptyTypes);

		private static readonly Lazy<MethodInfo> AmmoDisplayName = Method("Y4NGZUpgrades.Weapons.ArmoryPrizeApi", "GetAmmoDisplayName", OneString);

		private static readonly Lazy<MethodInfo> AmmoPrizePrefab = Method("Y4NGZUpgrades.Weapons.ArmoryPrizeApi", "GetAmmoPrizePrefab", OneString);

		private static readonly Lazy<MethodInfo> AmmoItem = Method("Y4NGZUpgrades.Weapons.ArmoryPrizeApi", "GetAmmoItem", OneString);

		private static readonly Lazy<MethodInfo> AmmoFamilyIds = Method("Y4NGZUpgrades.Weapons.ArmoryAmmoReserveApi", "GetAmmoFamilyIds", Type.EmptyTypes);

		private static readonly Lazy<MethodInfo> AmmoFamilyLabel = Method("Y4NGZUpgrades.Weapons.ArmoryAmmoReserveApi", "GetAmmoFamilyLabel", OneString);

		private static readonly Lazy<MethodInfo> AmmoFamilyReserve = Method("Y4NGZUpgrades.Weapons.ArmoryAmmoReserveApi", "GetAmmoFamilyReserve", OneString);

		private static readonly Lazy<MethodInfo> StopPresentation = Method("Y4NGZUpgrades.Weapons.ArmoryPresentationApi", "StopPresentationForHeldItemStow", new Type[1] { typeof(PlayerControllerB) });

		private static readonly HashSet<string> Warned = new HashSet<string>(StringComparer.Ordinal);

		internal static bool IsArmoryPresent
		{
			get
			{
				if (_presenceResolved)
				{
					return _present;
				}
				_presenceResolved = true;
				try
				{
					_present = Chainloader.PluginInfos != null && Chainloader.PluginInfos.ContainsKey("com.y4ngz.betterarmory");
				}
				catch
				{
					_present = false;
				}
				return _present;
			}
		}

		internal static string[] GetWeaponPrizeIds()
		{
			return Strings(WeaponPrizeIds);
		}

		internal static string GetWeaponDisplayName(string weaponId)
		{
			return (Invoke(WeaponDisplayName, weaponId) as string) ?? weaponId;
		}

		internal static GameObject GetWeaponPrizePrefab(string weaponId)
		{
			object obj = Invoke(WeaponPrizePrefab, weaponId);
			return (GameObject)((obj is GameObject) ? obj : null);
		}

		internal static Item GetWeaponItem(string weaponId)
		{
			object obj = Invoke(WeaponItem, weaponId);
			return (Item)((obj is Item) ? obj : null);
		}

		internal static string[] GetWeaponFingerprintTokens()
		{
			return Strings(WeaponFingerprint);
		}

		internal static void InitializeWeaponPrize(GameObject instance, string weaponId)
		{
			MethodInfo methodInfo = Resolve(WeaponPrizeInit);
			if (methodInfo == null || (Object)(object)instance == (Object)null)
			{
				return;
			}
			try
			{
				methodInfo.Invoke(null, new object[2] { instance, weaponId });
			}
			catch (Exception ex)
			{
				Warn("InitializeWeaponPrize", ex);
			}
		}

		internal static string[] GetAmmoPrizeIds()
		{
			return Strings(AmmoPrizeIds);
		}

		internal static string GetAmmoDisplayName(string pickupId)
		{
			return (Invoke(AmmoDisplayName, pickupId) as string) ?? pickupId;
		}

		internal static GameObject GetAmmoPrizePrefab(string pickupId)
		{
			object obj = Invoke(AmmoPrizePrefab, pickupId);
			return (GameObject)((obj is GameObject) ? obj : null);
		}

		internal static Item GetAmmoItem(string pickupId)
		{
			object obj = Invoke(AmmoItem, pickupId);
			return (Item)((obj is Item) ? obj : null);
		}

		internal static string[] GetAmmoFamilyIds()
		{
			return Strings(AmmoFamilyIds);
		}

		internal static string GetAmmoFamilyLabel(string familyId)
		{
			return (Invoke(AmmoFamilyLabel, familyId) as string) ?? familyId;
		}

		internal static int GetAmmoFamilyReserve(string familyId)
		{
			object obj = Invoke(AmmoFamilyReserve, familyId);
			if (obj is int)
			{
				return (int)obj;
			}
			return 0;
		}

		internal static void StopPresentationForHeldItemStow(PlayerControllerB player)
		{
			MethodInfo methodInfo = Resolve(StopPresentation);
			if (methodInfo == null || (Object)(object)player == (Object)null)
			{
				return;
			}
			try
			{
				methodInfo.Invoke(null, new object[1] { player });
			}
			catch (Exception ex)
			{
				Warn("StopPresentationForHeldItemStow", ex);
			}
		}

		private static Lazy<MethodInfo> Method(string typeName, string methodName, Type[] parameters)
		{
			return new Lazy<MethodInfo>(delegate
			{
				Type type = FindType(typeName);
				if (type == null)
				{
					return (MethodInfo)null;
				}
				MethodInfo method = type.GetMethod(methodName, BindingFlags.Static | BindingFlags.Public, null, parameters, null);
				if (method == null)
				{
					ManualLogSource log = Plugin.Log;
					if (log != null)
					{
						log.LogWarning((object)("[ArmoryBridge] " + typeName + "." + methodName + " was not found. That bridge is disabled for this session."));
					}
				}
				return method;
			});
		}

		private static MethodInfo Resolve(Lazy<MethodInfo> lazy)
		{
			try
			{
				return lazy.Value;
			}
			catch
			{
				return null;
			}
		}

		private static object Invoke(Lazy<MethodInfo> lazy, string argument)
		{
			MethodInfo methodInfo = Resolve(lazy);
			if (methodInfo == null)
			{
				return null;
			}
			try
			{
				return methodInfo.Invoke(null, new object[1] { argument });
			}
			catch (Exception ex)
			{
				Warn(methodInfo.Name, ex);
				return null;
			}
		}

		private static string[] Strings(Lazy<MethodInfo> lazy)
		{
			MethodInfo methodInfo = Resolve(lazy);
			if (methodInfo == null)
			{
				return NoIds;
			}
			try
			{
				return (methodInfo.Invoke(null, null) as string[]) ?? NoIds;
			}
			catch (Exception ex)
			{
				Warn(methodInfo.Name, ex);
				return NoIds;
			}
		}

		private static void Warn(string member, Exception ex)
		{
			if (Warned.Add(member))
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("[ArmoryBridge] " + member + " failed safely: " + ex.Message));
				}
			}
		}

		private static Type FindType(string fullName)
		{
			if (!IsArmoryPresent)
			{
				return null;
			}
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly in assemblies)
			{
				try
				{
					Type type = assembly.GetType(fullName, throwOnError: false);
					if (type != null)
					{
						return type;
					}
				}
				catch
				{
				}
			}
			if (IsArmoryPresent)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("[ArmoryBridge] Better Armory is installed but '" + fullName + "' was not found. That bridge is disabled for this session."));
				}
			}
			return null;
		}
	}
	internal static class ArmoryItemProbe
	{
		private const string WeaponNamespacePrefix = "Y4NGZUpgrades.Weapons.";

		internal static bool IsArmoryWeapon(GrabbableObject item)
		{
			if ((Object)(object)item == (Object)null)
			{
				return false;
			}
			Component[] components = ((Component)item).GetComponents<Component>();
			foreach (Component val in components)
			{
				if (!((Object)(object)val == (Object)null))
				{
					string fullName = ((object)val).GetType().FullName;
					if (fullName != null && fullName.StartsWith("Y4NGZUpgrades.Weapons.", StringComparison.Ordinal))
					{
						return true;
					}
				}
			}
			return false;
		}
	}
	public static class ClutchXpPolicy
	{
		public static bool IsEligible(bool localEnteredFacility, bool localExtractedAlive, int otherFacilityEntrants, int deadOtherFacilityEntrants)
		{
			if (localEnteredFacility && localExtractedAlive && otherFacilityEntrants > 0)
			{
				return deadOtherFacilityEntrants == otherFacilityEntrants;
			}
			return false;
		}
	}
	internal static class CompanyQuotaTokenIntegration
	{
		[HarmonyPatch(typeof(StartOfRound), "Awake")]
		private static class StartOfRoundAwakePatch
		{
			private static void Postfix()
			{
				EnsureRegistered();
			}
		}

		[HarmonyPatch(typeof(GameNetworkManager), "Disconnect")]
		private static class DisconnectPatch
		{
			private static void Prefix()
			{
				Shutdown();
			}
		}

		[CompilerGenerated]
		private static class <>O
		{
			public static HandleNamedMessageDelegate <0>__OnGrantMessage;
		}

		private const string CompanyApiTypeName = "Y4NGZCompany.Core.QuotaProgressionApi";

		private const string GrantMessageName = "Y4NGZUpgrades.CompanyQuotaTokenGrant.v1";

		private const string CompanyProtocolVersionMember = "TokenGrantProtocolVersion";

		private const int MaxActionIdCharacters = 120;

		private const int LegacyCompanyProtocolVersion = 1;

		private static NetworkManager _registeredNetworkManager;

		private static object _companyHandler;

		private static MethodInfo _companyUnregister;

		private static bool _loggedRequestShapeError;

		internal static bool IsCompanyProviderRegistered => _companyHandler != null;

		internal static void EnsureRegistered()
		{
			RegisterNetworkHandler();
			RegisterCompanyHandler();
		}

		internal static void Shutdown()
		{
			UnregisterCompanyHandler();
			UnregisterNetworkHandler();
		}

		private static void RegisterCompanyHandler()
		{
			if (_companyHandler != null)
			{
				return;
			}
			Type type = FindType("Y4NGZCompany.Core.QuotaProgressionApi");
			if (type == null || !IsCompanyProtocolCompatible(type))
			{
				return;
			}
			MethodInfo method = type.GetMethod("RegisterTokenGrantHandler", BindingFlags.Static | BindingFlags.Public);
			_companyUnregister = type.GetMethod("UnregisterTokenGrantHandler", BindingFlags.Static | BindingFlags.Public);
			ParameterInfo[] array = method?.GetParameters();
			if (array == null || array.Length != 1)
			{
				return;
			}
			Type parameterType = array[0].ParameterType;
			MethodInfo method2 = parameterType.GetMethod("Invoke");
			ParameterInfo[] array2 = method2?.GetParameters();
			if (method2 == null || method2.ReturnType != typeof(bool) || array2 == null || array2.Length != 1 || !HasRequiredRequestFields(array2[0].ParameterType))
			{
				return;
			}
			try
			{
				ParameterExpression parameterExpression = Expression.Parameter(array2[0].ParameterType, "request");
				MethodInfo method3 = typeof(CompanyQuotaTokenIntegration).GetMethod("HandleCompanyRequest", BindingFlags.Static | BindingFlags.NonPublic);
				_companyHandler = Expression.Lambda(parameterType, Expression.Call(method3, Expression.Convert(parameterExpression, typeof(object))), parameterExpression).Compile();
				method.Invoke(null, new object[1] { _companyHandler });
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogInfo((object)"[QuotaTokens] Registered Company quota token provider.");
				}
			}
			catch (Exception ex)
			{
				_companyHandler = null;
				_companyUnregister = null;
				ManualLogSource log2 = Plugin.Log;
				if (log2 != null)
				{
					log2.LogWarning((object)("[QuotaTokens] Company provider registration failed: " + ex.Message));
				}
			}
		}

		private static void UnregisterCompanyHandler()
		{
			if (_companyHandler == null)
			{
				return;
			}
			try
			{
				_companyUnregister?.Invoke(null, new object[1] { _companyHandler });
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("[QuotaTokens] Company provider unregister failed: " + ex.Message));
				}
			}
			_companyHandler = null;
			_companyUnregister = null;
		}

		private static bool IsCompanyProtocolCompatible(Type apiType)
		{
			FieldInfo field = apiType.GetField("TokenGrantProtocolVersion", BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy);
			int num;
			if (field == null)
			{
				num = 1;
			}
			else
			{
				if (!(field.GetValue(null) is int num2))
				{
					ManualLogSource log = Plugin.Log;
					if (log != null)
					{
						log.LogWarning((object)("[QuotaTokens] Not registering: Company TokenGrantProtocolVersion is not an int " + $"(Upgrades protocol {1}). Update Y4NGZUpgrades and Y4NGZCompany together."));
					}
					return false;
				}
				num = num2;
			}
			if (num == 1)
			{
				return true;
			}
			ManualLogSource log2 = Plugin.Log;
			if (log2 != null)
			{
				log2.LogWarning((object)("[QuotaTokens] Not registering: token-grant protocol mismatch " + $"(Y4NGZUpgrades {1}, Y4NGZCompany {num}). " + "Quota token rewards are disabled until both mods are updated together."));
			}
			return false;
		}

		private static bool HasRequiredRequestFields(Type requestType)
		{
			string empty = string.Empty;
			empty = AppendMissing(empty, requestType, "CompletedQuota", typeof(int));
			empty = AppendMissing(empty, requestType, "TokensPerPlayer", typeof(int));
			empty = AppendMissing(empty, requestType, "ActionId", typeof(string));
			if (empty.Length == 0)
			{
				return true;
			}
			ManualLogSource log = Plugin.Log;
			if (log != null)
			{
				log.LogWarning((object)("[QuotaTokens] Not registering: Company request type '" + requestType.FullName + "' is missing expected field(s): " + empty + ". Quota token rewards are disabled until both mods are updated together."));
			}
			return false;
		}

		private static string AppendMissing(string missing, Type requestType, string name, Type expected)
		{
			FieldInfo field = requestType.GetField(name, BindingFlags.Instance | BindingFlags.Public);
			if (field != null && field.FieldType == expected)
			{
				return missing;
			}
			string text = ((field == null) ? name : (name + " (expected " + expected.Name + ", found " + field.FieldType.Name + ")"));
			if (missing.Length != 0)
			{
				return missing + ", " + text;
			}
			return text;
		}

		private static bool HandleCompanyRequest(object request)
		{
			NetworkManager singleton = NetworkManager.Singleton;
			if (request == null || (Object)(object)singleton == (Object)null || !singleton.IsServer)
			{
				return false;
			}
			try
			{
				Type type = request.GetType();
				if (!TryReadIntField(type, request, "CompletedQuota", out var value) || !TryReadIntField(type, request, "TokensPerPlayer", out var value2) || !TryReadStringField(type, request, "ActionId", out var value3))
				{
					return false;
				}
				bool isReplay = ReadOptionalBoolField(type, request, "IsReplay");
				if (value < 1 || value2 < 1 || string.IsNullOrWhiteSpace(value3))
				{
					return false;
				}
				return TryGrantConnectedPlayers(new ExternalTokenGrantRequest(value2, "Y4NGZCompany", $"quota:{value}", value3), isReplay);
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("[QuotaTokens] Company grant failed: " + ex.Message));
				}
				return false;
			}
		}

		internal static bool TryGrantConnectedPlayers(ExternalTokenGrantRequest request)
		{
			return TryGrantConnectedPlayers(request, isReplay: false);
		}

		internal unsafe static bool TryGrantConnectedPlayers(ExternalTokenGrantRequest request, bool isReplay)
		{
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager singleton = NetworkManager.Singleton;
			if ((Object)(object)singleton == (Object)null || !singleton.IsServer || request.AmountPerPlayer < 1)
			{
				return false;
			}
			string text = (string.IsNullOrWhiteSpace(request.Source) ? "external" : request.Source.Trim());
			string text2 = (string.IsNullOrWhiteSpace(request.ActionId) ? string.Empty : request.ActionId.Trim());
			string text3 = text + ":" + text2;
			int completedQuota = ParseQuota(request.MilestoneId);
			if (text2.Length == 0)
			{
				return false;
			}
			try
			{
				if (text3.Length > 120)
				{
					ManualLogSource log = Plugin.Log;
					if (log != null)
					{
						log.LogWarning((object)("[QuotaTokens] Rejected " + text + " grant with oversized action ID."));
					}
					return false;
				}
				bool result = ApplyLocalGrant(completedQuota, request.AmountPerPlayer, text3, isReplay);
				CustomMessagingManager customMessagingManager = singleton.CustomMessagingManager;
				if (customMessagingManager == null)
				{
					return result;
				}
				FastBufferWriter val = default(FastBufferWriter);
				((FastBufferWriter)(ref val))..ctor(256, (Allocator)2, -1);
				try
				{
					((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref completedQuota, default(ForPrimitives));
					((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref request.AmountPerPlayer, default(ForPrimitives));
					FixedString128Bytes val2 = new FixedString128Bytes(text3);
					((FastBufferWriter)(ref val)).WriteValueSafe<FixedString128Bytes>(ref val2, default(ForFixedStrings));
					foreach (ulong connectedClientsId in singleton.ConnectedClientsIds)
					{
						if (connectedClientsId != singleton.LocalClientId)
						{
							customMessagingManager.SendNamedMessage("Y4NGZUpgrades.CompanyQuotaTokenGrant.v1", connectedClientsId, val, (NetworkDelivery)4);
						}
					}
				}
				finally
				{
					((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose();
				}
				return true;
			}
			catch (Exception ex)
			{
				ManualLogSource log2 = Plugin.Log;
				if (log2 != null)
				{
					log2.LogWarning((object)("[QuotaTokens] " + text + " grant failed: " + ex.Message));
				}
				return false;
			}
		}

		private static bool ApplyLocalGrant(int completedQuota, int tokensPerPlayer, string actionId, bool isReplay = false)
		{
			if (!ProgressionManager.TryApplyExternalTokenGrant(actionId, tokensPerPlayer, out var alreadyApplied))
			{
				return false;
			}
			if (alreadyApplied)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogDebug((object)string.Format("[QuotaTokens] Quota {0} grant already in this save's ledger ({1}); ignoring{2}.", completedQuota, actionId, isReplay ? " replay" : string.Empty));
				}
				return true;
			}
			ManualLogSource log2 = Plugin.Log;
			if (log2 != null)
			{
				log2.LogInfo((object)string.Format("[QuotaTokens] Quota {0} grant accepted{1}: +{2} tokens ({3}).", completedQuota, isReplay ? " (replay)" : string.Empty, tokensPerPlayer, actionId));
			}
			return true;
		}

		private static void RegisterNetworkHandler()
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Expected O, but got Unknown
			NetworkManager singleton = NetworkManager.Singleton;
			if (((singleton != null) ? singleton.CustomMessagingManager : null) == null || (Object)(object)_registeredNetworkManager == (Object)(object)singleton)
			{
				return;
			}
			UnregisterNetworkHandler();
			try
			{
				CustomMessagingManager customMessagingManager = singleton.CustomMessagingManager;
				object obj = <>O.<0>__OnGrantMessage;
				if (obj == null)
				{
					HandleNamedMessageDelegate val = OnGrantMessage;
					<>O.<0>__OnGrantMessage = val;
					obj = (object)val;
				}
				customMessagingManager.RegisterNamedMessageHandler("Y4NGZUpgrades.CompanyQuotaTokenGrant.v1", (HandleNamedMessageDelegate)obj);
				_registeredNetworkManager = singleton;
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("[QuotaTokens] Network handler registration failed: " + ex.Message));
				}
			}
		}

		private static void UnregisterNetworkHandler()
		{
			NetworkManager registeredNetworkManager = _registeredNetworkManager;
			if (((registeredNetworkManager != null) ? registeredNetworkManager.CustomMessagingManager : null) != null)
			{
				try
				{
					_registeredNetworkManager.CustomMessagingManager.UnregisterNamedMessageHandler("Y4NGZUpgrades.CompanyQuotaTokenGrant.v1");
				}
				catch (Exception ex)
				{
					ManualLogSource log = Plugin.Log;
					if (log != null)
					{
						log.LogWarning((object)("[QuotaTokens] Network handler unregister failed: " + ex.Message));
					}
				}
			}
			_registeredNetworkManager = null;
		}

		private unsafe static void OnGrantMessage(ulong senderClientId, FastBufferReader reader)
		{
			//IL_0018: 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_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)NetworkManager.Singleton == (Object)null || senderClientId != 0L)
			{
				return;
			}
			try
			{
				int num = default(int);
				((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref num, default(ForPrimitives));
				int num2 = default(int);
				((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref num2, default(ForPrimitives));
				FixedString128Bytes val = default(FixedString128Bytes);
				((FastBufferReader)(ref reader)).ReadValueSafe<FixedString128Bytes>(ref val, default(ForFixedStrings));
				if (num >= 1 && num2 >= 1 && !((FixedString128Bytes)(ref val)).IsEmpty)
				{
					ApplyLocalGrant(num, num2, ((object)(*(FixedString128Bytes*)(&val))/*cast due to .constrained prefix*/).ToString());
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("[QuotaTokens] Malformed grant from server: " + ex.Message));
				}
			}
		}

		private static Type FindType(string fullName)
		{
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly in assemblies)
			{
				try
				{
					Type type = assembly.GetType(fullName, throwOnError: false);
					if (type != null)
					{
						return type;
					}
				}
				catch
				{
				}
			}
			return null;
		}

		private static bool TryReadIntField(Type type, object instance, string name, out int value)
		{
			value = 0;
			if (type.GetField(name, BindingFlags.Instance | BindingFlags.Public)?.GetValue(instance) is int num)
			{
				value = num;
				return true;
			}
			LogRequestShapeError(type, name, "int");
			return false;
		}

		private static bool TryReadStringField(Type type, object instance, string name, out string value)
		{
			value = string.Empty;
			FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public);
			if (field != null && field.FieldType == typeof(string))
			{
				value = (field.GetValue(instance) as string) ?? string.Empty;
				return true;
			}
			LogRequestShapeError(type, name, "string");
			return false;
		}

		private static bool ReadOptionalBoolField(Type type, object instance, string name)
		{
			object obj = type.GetField(name, BindingFlags.Instance | BindingFlags.Public)?.GetValue(instance);
			bool flag = default(bool);
			int num;
			if (obj is bool)
			{
				flag = (bool)obj;
				num = 1;
			}
			else
			{
				num = 0;
			}
			return (byte)((uint)num & (flag ? 1u : 0u)) != 0;
		}

		private static void LogRequestShapeError(Type type, string name, string expected)
		{
			if (!_loggedRequestShapeError)
			{
				_loggedRequestShapeError = true;
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogError((object)("[QuotaTokens] Company request type '" + type.FullName + "' has no readable " + expected + " field '" + name + "'. " + $"Quota token grants are being dropped; Y4NGZUpgrades expects token-grant protocol {1}. " + "Update Y4NGZUpgrades and Y4NGZCompany together."));
				}
			}
		}

		private static int ParseQuota(string milestoneId)
		{
			if (string.IsNullOrWhiteSpace(milestoneId))
			{
				return 0;
			}
			int num = milestoneId.LastIndexOf(':');
			if (!int.TryParse((num >= 0) ? milestoneId.Substring(num + 1) : milestoneId, out var result))
			{
				return 0;
			}
			return Math.Max(0, result);
		}
	}
	internal static class ContractEventAttribution
	{
		internal const string CrewFanOutMarker = ".crew.";

		internal static bool IsIndividuallyAttributed(string eventId, ulong creditedClientId)
		{
			if (string.IsNullOrEmpty(eventId))
			{
				return false;
			}
			if (!eventId.EndsWith("." + creditedClientId, StringComparison.Ordinal))
			{
				return false;
			}
			return eventId.IndexOf(".crew.", StringComparison.Ordinal) < 0;
		}
	}
	internal sealed class CumulativeCountTracker
	{
		private readonly Dictionary<int, int> _deltaByTotal = new Dictionary<int, int>();

		private int _highWater;

		internal int Observe(int cumulativeTotal)
		{
			if (cumulativeTotal <= 0)
			{
				return 1;
			}
			if (cumulativeTotal > _highWater)
			{
				int num = cumulativeTotal - _highWater;
				_highWater = cumulativeTotal;
				_deltaByTotal[cumulativeTotal] = num;
				return num;
			}
			if (!_deltaByTotal.TryGetValue(cumulativeTotal, out var value))
			{
				return 0;
			}
			return value;
		}
	}
	internal static class DawnLibCompat
	{
		internal const string ItemNamespace = "y4ngz_upgrades";

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		internal static void RegisterNetworkPrefab(GameObject prefab)
		{
			DawnLib.RegisterNetworkPrefab(prefab);
		}

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		internal static void FixMixerGroups(GameObject prefab)
		{
			DawnLib.FixMixerGroups(prefab);
		}

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		internal static void RegisterItem(string itemKey, Item item)
		{
			if (!((Object)(object)item == (Object)null) && !string.IsNullOrWhiteSpace(itemKey))
			{
				DawnLib.DefineItem(NamespacedKey<DawnItemInfo>.From("y4ngz_upgrades", itemKey), item, (Action<ItemInfoBuilder>)delegate
				{
				});
			}
		}
	}
	internal sealed class DeliveryAttributionLedger
	{
		internal const ulong UnattributedHandler = ulong.MaxValue;

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

		private readonly HashSet<ulong> _preexistingInsideKeys = new HashSet<ulong>();

		internal int PreexistingInsideCount => _preexistingInsideKeys.Count;

		internal void Reset()
		{
			_lastHandlerByKey.Clear();
			_preexistingInsideKeys.Clear();
		}

		internal void MarkPreexistingInside(ulong key)
		{
			_preexistingInsideKeys.Add(key);
		}

		internal void RecordBoundaryCrossing(ulong key, ulong handlerClientId, bool nowInside)
		{
			if (nowInside)
			{
				_lastHandlerByKey[key] = handlerClientId;
			}
			else
			{
				_lastHandlerByKey.Remove(key);
			}
		}

		internal static bool SuppressOutwardTransition(bool nowInside, bool handlerKnown, bool handlerIsDead, bool handlerIsInsideShip)
		{
			if (!nowInside && handlerKnown)
			{
				return handlerIsDead || handlerIsInsideShip;
			}
			return false;
		}

		internal static bool ShouldPayBodyRetrieval(bool lastHandlerIsPayee, bool bodyIsInShip, bool bodyDeactivated, bool ownerResolved, bool payeeOwnsBody)
		{
			if (lastHandlerIsPayee && bodyIsInShip && !bodyDeactivated && ownerResolved)
			{
				return !payeeOwnsBody;
			}
			return false;
		}

		internal bool TryGetDeliveryHandler(ulong key, out ulong handlerClientId)
		{
			return _lastHandlerByKey.TryGetValue(key, out handlerClientId);
		}

		internal bool ShouldPayDelivery(ulong key, bool insideAtRoundEnd, ulong localClientId)
		{
			if (insideAtRoundEnd && !_preexistingInsideKeys.Contains(key) && _lastHandlerByKey.TryGetValue(key, out var value) && value != ulong.MaxValue)
			{
				return value == localClientId;
			}
			return false;
		}
	}
	internal static class EffectiveConfigInventory
	{
		private readonly struct InventoryRow
		{
			internal string FileName { get; }

			internal ConfigEntryBase Entry { get; }

			internal InventoryRow(string fileName, ConfigEntryBase entry)
			{
				FileName = fileName;
				Entry = entry;
			}
		}

		internal static string ReportPath => Path.Combine(Paths.ConfigPath, "Y4NGZUpgrades", "effective-config.tsv");

		internal static void Write(IEnumerable<ConfigFile> configs)
		{
			if (configs == null)
			{
				return;
			}
			try
			{
				List<InventoryRow> list = new List<InventoryRow>();
				foreach (ConfigFile config in configs)
				{
					if (config == null)
					{
						continue;
					}
					string fileName = Path.GetFileName(config.ConfigFilePath);
					foreach (KeyValuePair<ConfigDefinition, ConfigEntryBase> item in config)
					{
						list.Add(new InventoryRow(fileName, item.Value));
					}
				}
				list.Sort(delegate(InventoryRow left, InventoryRow right)
				{
					int num2 = string.Compare(left.FileName, right.FileName, StringComparison.OrdinalIgnoreCase);
					if (num2 != 0)
					{
						return num2;
					}
					int num3 = string.Compare(left.Entry.Definition.Section, right.Entry.Definition.Section, StringComparison.OrdinalIgnoreCase);
					return (num3 == 0) ? string.Compare(left.Entry.Definition.Key, right.Entry.Definition.Key, StringComparison.OrdinalIgnoreCase) : num3;
				});
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("file\tsection\tkey\ttype\tdefault\teffective\tdescription");
				for (int num = 0; num < list.Count; num++)
				{
					InventoryRow inventoryRow = list[num];
					ConfigEntryBase entry = inventoryRow.Entry;
					StringBuilder stringBuilder2 = stringBuilder.Append(Escape(inventoryRow.FileName)).Append('\t').Append(Escape(entry.Definition.Section))
						.Append('\t')
						.Append(Escape(entry.Definition.Key))
						.Append('\t')
						.Append(Escape(entry.SettingType?.FullName))
						.Append('\t')
						.Append(Escape(Format(entry.DefaultValue)))
						.Append('\t')
						.Append(Escape(Format(entry.BoxedValue)))
						.Append('\t');
					ConfigDescription description = entry.Description;
					stringBuilder2.Append(Escape((description != null) ? description.Description : null)).AppendLine();
				}
				Directory.CreateDirectory(Path.GetDirectoryName(ReportPath));
				File.WriteAllText(ReportPath, stringBuilder.ToString());
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogInfo((object)$"Effective config inventory written to '{ReportPath}' ({list.Count} definitions).");
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log2 = Plugin.Log;
				if (log2 != null)
				{
					log2.LogWarning((object)("Failed writing effective config inventory: " + ex.Message));
				}
			}
		}

		private static string Format(object value)
		{
			if (value == null)
			{
				return string.Empty;
			}
			if (!(value is IFormattable formattable))
			{
				return value.ToString();
			}
			return formattable.ToString(null, CultureInfo.InvariantCulture);
		}

		private static string Escape(string value)
		{
			return (value ?? string.Empty).Replace("\t", "\\t").Replace("\r", "\\r").Replace("\n", "\\n");
		}
	}
	[Serializable]
	internal sealed class EmployeeStatisticsData
	{
		public int monstersKilled;

		public int stepsTaken;

		public int scrapValueDelivered;

		public int timesDied;

		public int bombsDefused;

		public float payloadDistancePushedMeters;

		public int surveyBeaconsPlaced;

		public int itemsIncinerated;

		public int whistleblowerDamageDealt;

		public int pestsTrapped;

		public int containmentWavesSurvived;

		public int drillsPlaced;

		public int breakersRestored;

		public float timeSpentOnCctvSeconds;

		public int devicesHacked;

		public int quotasCompleted;

		internal EmployeeStatisticsData Clone()
		{
			return new EmployeeStatisticsData
			{
				monstersKilled = monstersKilled,
				stepsTaken = stepsTaken,
				scrapValueDelivered = scrapValueDelivered,
				timesDied = timesDied,
				bombsDefused = bombsDefused,
				payloadDistancePushedMeters = payloadDistancePushedMeters,
				surveyBeaconsPlaced = surveyBeaconsPlaced,
				itemsIncinerated = itemsIncinerated,
				whistleblowerDamageDealt = whistleblowerDamageDealt,
				pestsTrapped = pestsTrapped,
				containmentWavesSurvived = containmentWavesSurvived,
				drillsPlaced = drillsPlaced,
				breakersRestored = breakersRestored,
				timeSpentOnCctvSeconds = timeSpentOnCctvSeconds,
				devicesHacked = devicesHacked,
				quotasCompleted = quotasCompleted
			};
		}

		internal void Add(EmployeeStatisticsData other)
		{
			if (other != null)
			{
				monstersKilled = AddClamped(monstersKilled, other.monstersKilled);
				stepsTaken = AddClamped(stepsTaken, other.stepsTaken);
				scrapValueDelivered = AddClamped(scrapValueDelivered, other.scrapValueDelivered);
				timesDied = AddClamped(timesDied, other.timesDied);
				bombsDefused = AddClamped(bombsDefused, other.bombsDefused);
				payloadDistancePushedMeters = AddClamped(payloadDistancePushedMeters, other.payloadDistancePushedMeters);
				surveyBeaconsPlaced = AddClamped(surveyBeaconsPlaced, other.surveyBeaconsPlaced);
				itemsIncinerated = AddClamped(itemsIncinerated, other.itemsIncinerated);
				whistleblowerDamageDealt = AddClamped(whistleblowerDamageDealt, other.whistleblowerDamageDealt);
				pestsTrapped = AddClamped(pestsTrapped, other.pestsTrapped);
				containmentWavesSurvived = AddClamped(containmentWavesSurvived, other.containmentWavesSurvived);
				drillsPlaced = AddClamped(drillsPlaced, other.drillsPlaced);
				breakersRestored = AddClamped(breakersRestored, other.breakersRestored);
				timeSpentOnCctvSeconds = AddClamped(timeSpentOnCctvSeconds, other.timeSpentOnCctvSeconds);
				devicesHacked = AddClamped(devicesHacked, other.devicesHacked);
				quotasCompleted = AddClamped(quotasCompleted, other.quotasCompleted);
			}
		}

		private static int AddClamped(int left, int right)
		{
			long val = (long)Math.Max(0, left) + (long)Math.Max(0, right);
			return (int)Math.Min(2147483647L, val);
		}

		private static float AddClamped(float left, float right)
		{
			if (float.IsNaN(left) || float.IsInfinity(left))
			{
				left = 0f;
			}
			if (float.IsNaN(right) || float.IsInfinity(right))
			{
				right = 0f;
			}
			return Mathf.Clamp(Mathf.Max(0f, left) + Mathf.Max(0f, right), 0f, 1E+09f);
		}
	}
	internal static class EmployeeStatistics
	{
		internal readonly struct ReportNoteCandidate
		{
			internal readonly int Priority;

			internal readonly string Text;

			internal ReportNoteCandidate(int priority, string text)
			{
				Priority = priority;
				Text = text;
			}
		}

		private sealed class RoundState
		{
			internal readonly EmployeeStatisticsData Data = new EmployeeStatisticsData();

			internal readonly Dictionary<ulong, ulong> LastItemHolderByKey = new Dictionary<ulong, ulong>();

			internal readonly Dictionary<ulong, float> LastEnemyHitByLocalPlayer = new Dictionary<ulong, float>();

			internal readonly HashSet<ulong> KilledEnemies = new HashSet<ulong>();

			internal readonly HashSet<string> UniqueEventKeys = new HashSet<string>(StringComparer.Ordinal);

			internal Vector3 LastPlayerPosition;

			internal bool PlayerPositionValid;

			internal float StepDistance;

			internal object PayloadCart;

			internal Vector3 LastPayloadPosition;

			internal bool PayloadPositionValid;

			internal readonly CumulativeCountTracker PestCaptureCounts = new CumulativeCountTracker();
		}

		private const string CompanyAssemblyName = "Y4NGZCompany";

		private const string CctvAssemblyName = "LethalCCTV";

		internal const float StepMeters = 0.76f;

		private const float MinimumTrackedMovement = 0.02f;

		private const float MaximumTrackedMovement = 8f;

		private static readonly string SaveDir = Path.Combine(Paths.ConfigPath, "Y4NGZEmployeeFile");

		private static EmployeeStatisticsData _lifetime;

		private static EmployeeStatisticsData _lastRound;

		private static RoundState _round = new RoundState();

		private static readonly RoundLatch _latch = new RoundLatch();

		private static string _key;

		private static int _lastTimesFulfilledQuota = -1;

		private static bool _cctvReflectionResolved;

		private static PropertyInfo _cctvFocusedProperty;

		private static bool _payloadReflectionResolved;

		private static PropertyInfo _localPayloadCartProperty;

		private static PropertyInfo _payloadAttachedToLocalProperty;

		private static readonly string[] SpelledNumbers = new string[11]
		{
			"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine",
			"ten"
		};

		internal static EmployeeStatisticsData CurrentSnapshot
		{
			get
			{
				EnsureLoaded();
				EmployeeStatisticsData employeeStatisticsData = _lifetime?.Clone() ?? new EmployeeStatisticsData();
				if (_latch.Active && !_latch.Finalized)
				{
					employeeStatisticsData.Add(_round.Data);
				}
				return employeeStatisticsData;
			}
		}

		internal static EmployeeStatisticsData LastRoundSnapshot => _lastRound?.Clone();

		internal static void SwitchToCurrentSave()
		{
			if (!SaveKey.TryGetCurrent(out var key))
			{
				_key = null;
				_lifetime = new EmployeeStatisticsData();
				ResetRuntimeState();
			}
			else if (_lifetime == null || !string.Equals(_key, key, StringComparison.OrdinalIgnoreCase))
			{
				_key = key;
				_lifetime = Load(key);
				_lastRound = null;
				_round = new RoundState();
				_latch.Abandon();
				_lastTimesFulfilledQuota = CurrentQuotaCount();
				ResetPositionTracking();
			}
		}

		internal static void BeginRound()
		{
			SwitchToCurrentSave();
			_round = new RoundState();
			_latch.Begin();
			_lastRound = null;
			_lastTimesFulfilledQuota = CurrentQuotaCount();
			ResetPositionTracking();
		}

		internal static void AbandonUnfinalizedRound()
		{
			if (!_latch.Finalized && _latch.Active)
			{
				_latch.Abandon();
				_round = new RoundState();
				ResetPositionTracking();
			}
		}

		internal static void ResetCurrentSave()
		{
			if (!SaveKey.TryGetCurrentExistingOrSlot(out var key))
			{
				_key = null;
				_lifetime = new EmployeeStatisticsData();
				ResetRuntimeState();
			}
			else
			{
				DeleteForKey(key);
			}
		}

		internal static bool DeleteForKey(string key)
		{
			bool result = false;
			try
			{
				string path = GetPath(key);
				if (File.Exists(path))
				{
					File.Delete(path);
					result = true;
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("[EmployeeFile] Failed resetting statistics: " + ex.Message));
				}
			}
			if (string.Equals(_key, key, StringComparison.OrdinalIgnoreCase))
			{
				_key = null;
				_lifetime = new EmployeeStatisticsData();
			}
			ResetRuntimeState();
			return result;
		}

		internal static void RecordItemGrabbed(GrabbableObject item)
		{
			if (_latch.Active && !_latch.Finalized && !((Object)(object)item == (Object)null))
			{
				PlayerControllerB playerHeldBy = item.playerHeldBy;
				if ((Object)(object)playerHeldBy != (Object)null)
				{
					_round.LastItemHolderByKey[NetworkKey((Component)(object)item)] = playerHeldBy.actualClientId;
				}
			}
		}

		internal static void RecordEnemyHit(EnemyAI enemy, PlayerControllerB playerWhoHit)
		{
			if (_latch.Active && !_latch.Finalized && !((Object)(object)enemy == (Object)null) && IsLocalPlayer(playerWhoHit))
			{
				_round.LastEnemyHitByLocalPlayer[NetworkKey((Component)(object)enemy)] = Time.time;
			}
		}

		internal static void RecordEnemyKilled(EnemyAI enemy)
		{
			if (_latch.Active && !_latch.Finalized && !((Object)(object)enemy == (Object)null))
			{
				ulong num = NetworkKey((Component)(object)enemy);
				if (_round.KilledEnemies.Add(num) && _round.LastEnemyHitByLocalPlayer.TryGetValue(num, out var value) && !(Time.time - value > Mathf.Max(1f, Plugin.ProgressionConfig.KillAttributionWindowSeconds.Value)))
				{
					_round.Data.monstersKilled = AddOne(_round.Data.monstersKilled);
				}
			}
		}

		internal static void RecordDeath()
		{
			AddRoundOrLifetime(delegate(EmployeeStatisticsData data)
			{
				data.timesDied = AddOne(data.timesDied);
			});
		}

		internal static void RecordBombDefused(string eventId)
		{
			if (TryAddRoundKey("bomb." + (eventId ?? string.Empty)))
			{
				_round.Data.bombsDefused = AddOne(_round.Data.bombsDefused);
			}
		}

		internal static void RecordSurveyBeaconPlaced(string eventId)
		{
			if (TryAddRoundKey("survey." + (eventId ?? string.Empty)))
			{
				_round.Data.surveyBeaconsPlaced = AddOne(_round.Data.surveyBeaconsPlaced);
			}
		}

		internal static void RecordItemIncinerated(int playerId, ulong itemNetworkObjectId)
		{
			PlayerControllerB val = LocalPlayer();
			if (!((Object)(object)val == (Object)null) && (int)val.playerClientId == playerId && TryAddRoundKey("incinerator.item." + itemNetworkObjectId))
			{
				_round.Data.itemsIncinerated = AddOne(_round.Data.itemsIncinerated);
			}
		}

		internal static void RecordWhistleblowerDamage(EnemyAI enemy, PlayerControllerB playerWhoHit, int damage)
		{
			if (!((Object)(object)enemy == (Object)null) && damage > 0 && IsLocalPlayer(playerWhoHit) && _latch.Active && !_latch.Finalized)
			{
				_round.Data.whistleblowerDamageDealt = AddClamped(_round.Data.whistleblowerDamageDealt, damage);
			}
		}

		internal static void ObservePestsTrapped(string eventId, ulong creditedClientId, int capturedTotal)
		{
			if (_latch.Active && !_latch.Finalized)
			{
				int num = _round.PestCaptureCounts.Observe(capturedTotal);
				PlayerControllerB val = LocalPlayer();
				if (num > 0 && !((Object)(object)val == (Object)null) && val.actualClientId == creditedClientId && TryAddRoundKey("pest.trapped." + (eventId ?? string.Empty)))
				{
					_round.Data.pestsTrapped = AddClamped(_round.Data.pestsTrapped, num);
				}
			}
		}

		internal static void RecordContainmentWaveSurvived(string eventId)
		{
			if (TryAddRoundKey("containment.wave." + (eventId ?? string.Empty)))
			{
				_round.Data.containmentWavesSurvived = AddOne(_round.Data.containmentWavesSurvived);
			}
		}

		internal static void RecordDrillPlaced(string eventId)
		{
			if (TryAddRoundKey("shadowraid.drill." + (eventId ?? string.Empty)))
			{
				_round.Data.drillsPlaced = AddOne(_round.Data.drillsPlaced);
			}
		}

		internal static void RecordBreakerRestored(int restoredCount, ulong actorClientId)
		{
			PlayerControllerB val = LocalPlayer();
			if (!((Object)(object)val == (Object)null) && val.actualClientId == actorClientId && TryAddRoundKey("blackout.breaker.count." + Mathf.Max(1, restoredCount)))
			{
				_round.Data.breakersRestored = AddOne(_round.Data.breakersRestored);
			}
		}

		internal static void RecordSingleBreakerRestored(string eventId)
		{
			if (TryAddRoundKey("blackout.breaker.single." + (eventId ?? string.Empty)))
			{
				_round.Data.breakersRestored = AddOne(_round.Data.breakersRestored);
			}
		}

		internal static void RecordDeviceHacked(Object target)
		{
			RecordDeviceHacked((target != (Object)null) ? (((object)target).GetType().FullName + "." + target.GetInstanceID()) : ("unknown." + Time.frameCount));
		}

		internal static void RecordDeviceHacked(string targetKey)
		{
			if (TryAddRoundKey("hack." + (targetKey ?? string.Empty)))
			{
				_round.Data.devicesHacked = AddOne(_round.Data.devicesHacked);
			}
		}

		internal static void UpdateRuntime(PlayerControllerB localPlayer, float deltaTime)
		{
			if (_lifetime == null)
			{
				SwitchToCurrentSave();
			}
			UpdateQuotaCompletion();
			if (_latch.Active && !_latch.Finalized && IsLocalPlayer(localPlayer))
			{
				float num = Mathf.Clamp(deltaTime, 0f, 0.25f);
				UpdateSteps(localPlayer);
				if (IsCctvFocused())
				{
					_round.Data.timeSpentOnCctvSeconds += num;
				}
				UpdatePayloadDistance();
			}
		}

		internal static EmployeeStatisticsData FinalizeRound(int scrapCollected)
		{
			EnsureLoaded();
			if (!_latch.TryBeginFinalize(out var recoveredMissedStart))
			{
				return _lastRound?.Clone() ?? new EmployeeStatisticsData();
			}
			if (recoveredMissedStart)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("[EmployeeStatistics] FinalizeRound ran without a round start " + $"(sequence={_latch.Sequence}, scrapCollected={scrapCollected}). " + "Nothing was recorded this round — the RoundLifecycle.RoundStarted hook did not fire for this peer."));
				}
			}
			_round.Data.scrapValueDelivered = ComputeLocalDeliveredScrapValue();
			_lastRound = _round.Data.Clone();
			if (_lifetime == null)
			{
				_lifetime = new EmployeeStatisticsData();
			}
			_lifetime.Add(_lastRound);
			_latch.CompleteFinalize();
			Save();
			return _lastRound.Clone();
		}

		internal static IReadOnlyList<ReportNoteCandidate> BuildReportNoteCandidates()
		{
			List<ReportNoteCandidate> list = new List<ReportNoteCandidate>();
			EmployeeStatisticsData lastRound = _lastRound;
			if (lastRound == null)
			{
				return list;
			}
			if (lastRound.bombsDefused > 0)
			{
				list.Add(new ReportNoteCandidate(64, "* Defused " + FormatCount(lastRound.bombsDefused, "live bomb") + " during the operation."));
			}
			if (lastRound.surveyBeaconsPlaced > 0)
			{
				list.Add(new ReportNoteCandidate(60, "* Planted " + FormatCount(lastRound.surveyBeaconsPlaced, "survey beacon") + " across the site."));
			}
			if (lastRound.devicesHacked > 0)
			{
				list.Add(new ReportNoteCandidate(56, "* Hacked " + FormatCount(lastRound.devicesHacked, "secured device") + " during the operation."));
			}
			if (lastRound.payloadDistancePushedMeters >= 5f)
			{
				list.Add(new ReportNoteCandidate(52, $"* Pushed the payload {lastRound.payloadDistancePushedMeters:0}m across the site."));
			}
			if (lastRound.timeSpentOnCctvSeconds >= 20f)
			{
				list.Add(new ReportNoteCandidate(48, "* Monitored ship cameras for " + FormatDurationCompact(lastRound.timeSpentOnCctvSeconds) + "."));
			}
			if (lastRound.quotasCompleted > 0)
			{
				list.Add(new ReportNoteCandidate(40, "* Closed out the profit quota during this operation."));
			}
			return list;
		}

		private static string FormatCount(int count, string singularNoun)
		{
			int num = Mathf.Max(0, count);
			string text = ((num < SpelledNumbers.Length) ? SpelledNumbers[num] : num.ToString("N0"));
			if (num != 1)
			{
				return text + " " + singularNoun + "s";
			}
			return text + " " + singularNoun;
		}

		private static string FormatDurationCompact(float seconds)
		{
			int num = Mathf.Max(0, Mathf.FloorToInt(seconds));
			int num2 = num / 60;
			int num3 = num % 60;
			if (num2 <= 0)
			{
				return $"{num3}s";
			}
			return $"{num2}m {num3}s";
		}

		internal static string FormatDuration(float seconds)
		{
			int num = Mathf.Max(0, Mathf.FloorToInt(seconds));
			int num2 = num / 3600;
			int num3 = num % 3600 / 60;
			int num4 = num % 60;
			if (num2 <= 0)
			{
				return $"{num3:00}:{num4:00}";
			}
			return $"{num2}:{num3:00}:{num4:00}";
		}

		private static void EnsureLoaded()
		{
			if (_lifetime == null)
			{
				SwitchToCurrentSave();
			}
		}

		private static EmployeeStatisticsData Load(string key)
		{
			try
			{
				string path = GetPath(key);
				if (File.Exists(path))
				{
					return JsonUtility.FromJson<EmployeeStatisticsData>(File.ReadAllText(path)) ?? new EmployeeStatisticsData();
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("[EmployeeFile] Failed reading statistics: " + ex.Message));
				}
			}
			return new EmployeeStatisticsData();
		}

		private static void Save()
		{
			if (_lifetime == null || string.IsNullOrWhiteSpace(_key))
			{
				return;
			}
			try
			{
				Directory.CreateDirectory(SaveDir);
				File.WriteAllText(GetPath(_key), JsonUtility.ToJson((object)_lifetime, true));
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("[EmployeeFile] Failed writing statistics: " + ex.Message));
				}
			}
		}

		private static string GetPath(string key)
		{
			char[] invalidFileNameChars = Path.GetInvalidFileNameChars();
			char[] array = (key ?? "employee").ToCharArray();
			for (int i = 0; i < array.Length; i++)
			{
				if (Array.IndexOf(invalidFileNameChars, array[i]) >= 0)
				{
					array[i] = '_';
				}
			}
			return Path.Combine(SaveDir, new string(array) + ".json");
		}

		private static void UpdateSteps(PlayerControllerB player)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result t