Decompiled source of GoodItemScan v1.10.0

GoodItemScan.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using GoodItemScan.Patches;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using MonoMod.RuntimeDetour;
using TMPro;
using UnityEngine;
using UnityEngine.InputSystem;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: IgnoresAccessChecksTo("AmazingAssets.TerrainToMesh")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: IgnoresAccessChecksTo("ClientNetworkTransform")]
[assembly: IgnoresAccessChecksTo("DissonanceVoip")]
[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.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("UnityEngine.ARModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.NVIDIAModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.UI")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("TestAccount666.GoodItemScan")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Yet another scan mod")]
[assembly: AssemblyFileVersion("1.10.0.0")]
[assembly: AssemblyInformationalVersion("1.10.0+52b275a728e3a79f9d3453cdfd38babc23f4ecca")]
[assembly: AssemblyProduct("GoodItemScan")]
[assembly: AssemblyTitle("TestAccount666.GoodItemScan")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.10.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace GoodItemScan
{
	[Tooltip("This class is for mods like LGU that want to modify the scanner")]
	public static class CheatsAPI
	{
		public static int additionalDistance;

		public static int additionalEnemyDistance;

		public static int noLineOfSightDistance;
	}
	public static class ConfigManager
	{
		public static ConfigEntry<bool> preferClosestNodes;

		public static ConfigEntry<bool> alwaysRescan;

		public static ConfigEntry<int> scanNodesHardLimit;

		public static ConfigEntry<float> scanNodeDelay;

		public static ConfigEntry<bool> useDictionaryCache;

		public static ConfigEntry<bool> alwaysCheckForLineOfSight;

		public static ConfigEntry<int> maxScanNodesToProcessPerFrame;

		public static ConfigEntry<bool> updateScanNodeText;

		public static ConfigEntry<bool> sendDebugMessages;

		public static ConfigEntry<bool> showOpenedBlastDoorScanNode;

		public static ConfigEntry<bool> addBoxCollidersToInvalidScanNodes;

		public static ConfigEntry<bool> hideEmptyScanNodeSubText;

		public static ConfigEntry<int> totalAddWaitMultiplier;

		public static ConfigEntry<float> updateTimer;

		internal static void Initialize(ConfigFile configFile)
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Expected O, but got Unknown
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Expected O, but got Unknown
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Expected O, but got Unknown
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Expected O, but got Unknown
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Expected O, but got Unknown
			preferClosestNodes = configFile.Bind<bool>("General", "Prefer Closest Nodes", true, "If true, will prefer scanning the closest nodes first. This might cause performance issues.");
			alwaysRescan = configFile.Bind<bool>("General", "Always Rescan", true, "If true, will always start a fresh scan. This removes all previously scanned nodes from the UI.");
			scanNodesHardLimit = configFile.Bind<int>("General", "Scan Nodes Hard Limit", 120, new ConfigDescription("Defines the maximum amount of scan nodes on screen. If you feel like your screen is cluttered, try lowering this value.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(30, 666), Array.Empty<object>()));
			scanNodeDelay = configFile.Bind<float>("General", "Scan Node Delay", 0.1f, new ConfigDescription("Defines the delay between each scan node being added to the UI. This will look stupid if set too high. This value is divided by 100.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			useDictionaryCache = configFile.Bind<bool>("General", "Use Dictionary Cache", true, "May increase performance, at the cost of ram usage. If true, will use a dictionary for caching. If false, will not cache at all.");
			alwaysCheckForLineOfSight = configFile.Bind<bool>("General", "Always Check For Line Of Sight", false, "If true, will check for line of sight every frame. Enabling this could cause performance issues. Vanilla value is true.");
			maxScanNodesToProcessPerFrame = configFile.Bind<int>("General", "Max Scan Nodes To Process Per Frame", 32, new ConfigDescription("This value defines how many scan nodes can be processed each frame.This value is used in updating and scanning nodes!", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 666), Array.Empty<object>()));
			updateScanNodeText = configFile.Bind<bool>("General", "Update Scan Node Text", true, "If true, will update the scan node text. This is useful, if you, for example, have a mod that updates the value of an item.");
			sendDebugMessages = configFile.Bind<bool>("Debug", "Send Debug Messages", false, "If set to true, will spam your log with debug messages.");
			showOpenedBlastDoorScanNode = configFile.Bind<bool>("Special Cases", "Show opened blast door scan node", true, "If set to true, will allow you to scan nodes of opened blast doors (Vanilla value: false) Enabling this could improve performance.");
			addBoxCollidersToInvalidScanNodes = configFile.Bind<bool>("Special Cases", "Add BoxColliders To Invalid Scan Nodes", false, "If true, will add BoxColliers to ScanNodes that do not have one. It is not recommended to enable this. This feature was also never tested, so it might not even work.");
			hideEmptyScanNodeSubText = configFile.Bind<bool>("Special Cases", "Hide Empty Scan Node Sub Text", true, "I true, will hide the rectangle beneath the item name, if there's no text to be displayed.");
			totalAddWaitMultiplier = configFile.Bind<int>("Special Cases", "Total Add Wait Multiplier", 100, new ConfigDescription("This multiplier is used to define the wait time between adding more to the total displayed value. The lower this number, the faster the animation is updated.The lower this number, the less will be added per updated.For a vanilla-ish feeling, set this to 48.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 100), Array.Empty<object>()));
			updateTimer = configFile.Bind<float>("Special Cases", "Scan Node Update Timer", 1.2f, new ConfigDescription("This value is used to have a cooldown between scan node updates (Like position updates). The lower this number, the more often it will get updated.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 12f), Array.Empty<object>()));
		}
	}
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("TestAccount666.GoodItemScan", "GoodItemScan", "1.10.0")]
	public class GoodItemScan : BaseUnityPlugin
	{
		public static readonly List<Hook> Hooks = new List<Hook>();

		public static RectTransform originalRectTransform = null;

		public static Scanner? scanner;

		public static GoodItemScan Instance { get; private set; } = null;


		internal static ManualLogSource Logger { get; private set; } = null;


		internal static Harmony? Harmony { get; set; }

		private void Awake()
		{
			Logger = ((BaseUnityPlugin)this).Logger;
			Instance = this;
			ConfigManager.Initialize(((BaseUnityPlugin)this).Config);
			ConfigManager.scanNodesHardLimit.SettingChanged += delegate
			{
				SetIncreasedMaximumScanNodes(HUDManager.Instance);
			};
			Patch();
			HUDManagerPatch.InitMonoMod();
			UnpatchHdLethalCompany();
			Logger.LogInfo((object)"TestAccount666.GoodItemScan v1.10.0 has loaded!");
		}

		private static void UnpatchHdLethalCompany()
		{
			MethodInfo methodInfo = AccessTools.DeclaredMethod(typeof(HUDManager), "UpdateScanNodes", (Type[])null, (Type[])null);
			Patches patchInfo = Harmony.GetPatchInfo((MethodBase)methodInfo);
			if (patchInfo == null)
			{
				return;
			}
			ReadOnlyCollection<Patch> postfixes = patchInfo.Postfixes;
			int num = 0;
			Patch[] array = (Patch[])(object)new Patch[postfixes.Count];
			foreach (Patch item in postfixes)
			{
				array[num] = item;
				num++;
			}
			Patch[] array2 = array;
			foreach (Patch val in array2)
			{
				if (val != null && val.owner.ToLower().Contains("hdlethalcompany"))
				{
					Harmony? harmony = Harmony;
					if (harmony != null)
					{
						harmony.Unpatch((MethodBase)methodInfo, (HarmonyPatchType)2, val.owner);
					}
					Logger.LogInfo((object)"Found HDLethalCompany patch!");
					Logger.LogInfo((object)$"Unpatched {methodInfo} method!");
				}
			}
		}

		internal static void Patch()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			if (Harmony == null)
			{
				Harmony = new Harmony("TestAccount666.GoodItemScan");
			}
			LogDebug("Patching...");
			Harmony.PatchAll();
			LogDebug("Finished patching!");
		}

		internal static void Unpatch()
		{
			LogDebug("Unpatching...");
			Harmony? harmony = Harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			foreach (Hook hook in Hooks)
			{
				hook.Undo();
			}
			LogDebug("Finished unpatching!");
		}

		internal static void SetIncreasedMaximumScanNodes(HUDManager? hudManager)
		{
			if (!((Object)(object)hudManager == (Object)null))
			{
				RectTransform[] scanElements = hudManager.scanElements;
				foreach (RectTransform val in scanElements)
				{
					hudManager.scanNodes.Remove(val);
					((Component)val).gameObject.SetActive(false);
				}
				if (hudManager.scanElements.Length != 0)
				{
					originalRectTransform = hudManager.scanElements[0];
				}
				if ((Object)(object)originalRectTransform == (Object)null || !Object.op_Implicit((Object)(object)originalRectTransform))
				{
					Logger.LogFatal((object)"An error occured while trying to increase maximum scan nodes!");
					return;
				}
				hudManager.scanNodesHit = Array.Empty<RaycastHit>();
				hudManager.scanElements = Array.Empty<RectTransform>();
				scanner?.FillInScanNodes(originalRectTransform);
			}
		}

		internal static void LogDebug(object data)
		{
			if (ConfigManager.sendDebugMessages.Value)
			{
				Logger.LogInfo(data);
			}
		}
	}
	public class ScannedNode
	{
		private ScanNodeProperties? _scanNodeProperties;

		public Vector3 viewPoint;

		public GameObject scanNodeParent = null;

		public readonly RectTransform rectTransform;

		public readonly TextMeshProUGUI header;

		public readonly TextMeshProUGUI footer;

		public readonly GameObject subTextBox;

		public readonly int index;

		public bool hasScanNode;

		public ScanNodeProperties? ScanNodeProperties
		{
			get
			{
				return _scanNodeProperties;
			}
			set
			{
				_scanNodeProperties = value;
				hasScanNode = (Object)(object)value != (Object)null;
				if (hasScanNode)
				{
					scanNodeParent = ((Component)((Component)value).transform.parent).gameObject;
				}
			}
		}

		public ScannedNode(RectTransform rectTransform, TextMeshProUGUI header, TextMeshProUGUI footer, GameObject subTextBox, int index)
		{
			this.rectTransform = rectTransform;
			this.header = header;
			this.footer = footer;
			this.subTextBox = subTextBox;
			this.index = index;
			base..ctor();
		}
	}
	public class Scanner
	{
		private static readonly int _ColorNumberAnimatorHash = Animator.StringToHash("colorNumber");

		private static readonly int _DisplayAnimatorHash = Animator.StringToHash("display");

		private static readonly int _ScanAnimatorHash = Animator.StringToHash("scan");

		private Coroutine? _scanCoroutine;

		private Coroutine? _nodeVisibilityCheckCoroutine;

		private readonly HashSet<ScanNodeProperties> _scanNodesToRemove = new HashSet<ScanNodeProperties>();

		private readonly Dictionary<ScanNodeProperties, int> _scanNodes = new Dictionary<ScanNodeProperties, int>();

		private readonly List<ScannedNode> _scannedNodes = new List<ScannedNode>();

		private int _scrapScannedAmount;

		private int _scrapScannedValue;

		private readonly Dictionary<GameObject, (GrabbableObject?, EnemyAI?, TerminalAccessibleObject?)> _componentCache = new Dictionary<GameObject, (GrabbableObject, EnemyAI, TerminalAccessibleObject)>();

		private readonly Dictionary<Camera, float> _cachedFovValues = new Dictionary<Camera, float>();

		private readonly HashSet<ScannedNode> _scanNodesToUpdate = new HashSet<ScannedNode>();

		private float _updateTimer = 0.05f;

		private RectTransform _screenRectTransform = null;

		private int _scrapScannedValueDisplayed;

		private float _addToDisplayTotalInterval = 0.35f;

		public void FillInScanNodes(RectTransform originalRect)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			DisableAllScanElements();
			_scannedNodes.Clear();
			_cachedFovValues.Clear();
			int value = ConfigManager.scanNodesHardLimit.Value;
			for (int i = 0; i < value; i++)
			{
				RectTransform val = Object.Instantiate<RectTransform>(originalRect, ((Transform)originalRect).position, ((Transform)originalRect).rotation, ((Transform)originalRect).parent);
				Object.DontDestroyOnLoad((Object)(object)val);
				TextMeshProUGUI[] componentsInChildren = ((Component)val).gameObject.GetComponentsInChildren<TextMeshProUGUI>();
				TextMeshProUGUI header = componentsInChildren[0];
				TextMeshProUGUI val2 = componentsInChildren[1];
				GameObject gameObject = ((Component)((TMP_Text)val2).transform.parent.Find("SubTextBox")).gameObject;
				ScannedNode item = new ScannedNode(val, header, val2, gameObject, i);
				_scannedNodes.Add(item);
			}
			_nodeVisibilityCheckCoroutine = null;
			GameObject val3 = GameObject.Find("Systems/UI/Canvas/ObjectScanner");
			if ((Object)(object)val3 != (Object)null && Object.op_Implicit((Object)(object)val3))
			{
				val3.transform.SetSiblingIndex(3);
			}
			GameObject val4 = GameObject.Find("Systems/UI/Canvas/ObjectScanner/GlobalScanInfo");
			if ((Object)(object)val4 != (Object)null && Object.op_Implicit((Object)(object)val4))
			{
				val4.transform.SetAsLastSibling();
			}
		}

		public void Scan()
		{
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			PlayerControllerB localPlayerController = StartOfRound.Instance.localPlayerController;
			if (!((Object)(object)localPlayerController == (Object)null))
			{
				HUDManager instance = HUDManager.Instance;
				if (instance.CanPlayerScan() && !((double)instance.playerPingingScan > -1.0))
				{
					ResetScanState(instance);
					((Component)instance.scanEffectAnimator).transform.position = ((Component)localPlayerController.gameplayCamera).transform.position;
					instance.scanEffectAnimator.SetTrigger(_ScanAnimatorHash);
					instance.UIAudio.PlayOneShot(instance.scanSFX);
					GoodItemScan.LogDebug("Scan Initiated!");
					ScanNodeProperties[] array = Object.FindObjectsByType<ScanNodeProperties>((FindObjectsInactive)0, (FindObjectsSortMode)0);
					GoodItemScan.LogDebug($"Got '{array.Length}' nodes!");
					GoodItemScan.LogDebug($"Got '{_componentCache.Count}' nodes in cache!");
					_scanCoroutine = ((MonoBehaviour)instance).StartCoroutine(ScanNodes(localPlayerController, array));
				}
			}
		}

		private void ResetScanState(HUDManager hudManager)
		{
			if (_scanCoroutine != null)
			{
				((MonoBehaviour)hudManager).StopCoroutine(_scanCoroutine);
			}
			if (ConfigManager.alwaysRescan.Value)
			{
				DisableAllScanElements();
				_scrapScannedAmount = 0;
				_scrapScannedValue = 0;
			}
			hudManager.playerPingingScan = 0.3f;
		}

		public void DisableAllScanElements()
		{
			foreach (KeyValuePair<ScanNodeProperties, int> scanNode in _scanNodes)
			{
				scanNode.Deconstruct(out var _, out var value);
				int index = value;
				ScannedNode scannedNode = _scannedNodes[index];
				RectTransform rectTransform = scannedNode.rectTransform;
				if (Object.op_Implicit((Object)(object)rectTransform))
				{
					((Component)rectTransform).gameObject.SetActive(false);
				}
				scannedNode.ScanNodeProperties = null;
			}
			_scanNodes.Clear();
			HUDManager instance = HUDManager.Instance;
			if (_nodeVisibilityCheckCoroutine != null && (Object)(object)instance != (Object)null)
			{
				((MonoBehaviour)instance).StopCoroutine(_nodeVisibilityCheckCoroutine);
			}
			_nodeVisibilityCheckCoroutine = null;
		}

		private IEnumerator ScanNodes(PlayerControllerB localPlayer, ScanNodeProperties?[] scanNodes)
		{
			yield return null;
			int currentScanNodeCount = 0;
			Vector3 playerLocation = ((Component)localPlayer).transform.position;
			int processedNodesThisFrame = 0;
			if (ConfigManager.preferClosestNodes.Value)
			{
				scanNodes = (from node in scanNodes
					where (Object)(object)node != (Object)null
					select (node) into node
					orderby Vector3.Distance(playerLocation, ((Component)node).transform.position)
					select node).ToArray();
			}
			ScanNodeProperties?[] array = scanNodes;
			foreach (ScanNodeProperties scanNodeProperties in array)
			{
				if (processedNodesThisFrame >= ConfigManager.maxScanNodesToProcessPerFrame.Value)
				{
					yield return null;
					processedNodesThisFrame = 0;
				}
				processedNodesThisFrame++;
				if ((Object)(object)scanNodeProperties == (Object)null)
				{
					continue;
				}
				Vector3 scanNodePosition = ((Component)scanNodeProperties).transform.position;
				Vector3 viewPoint = GameNetworkManager.Instance.localPlayerController.gameplayCamera.WorldToViewportPoint(scanNodePosition);
				float x = viewPoint.x;
				int num;
				if (x >= 0f && x <= 1f)
				{
					float y = viewPoint.y;
					if (y >= 0f)
					{
						num = ((y <= 1f) ? 1 : 0);
						goto IL_01fa;
					}
				}
				num = 0;
				goto IL_01fa;
				IL_01fa:
				if (num == 0)
				{
					continue;
				}
				float distance = viewPoint.z;
				if (!(distance > (float)(scanNodeProperties.maxRange + ((scanNodeProperties.nodeType == 1) ? CheatsAPI.additionalEnemyDistance : CheatsAPI.additionalDistance))) && !(distance < (float)scanNodeProperties.minRange) && (!(distance > (float)CheatsAPI.noLineOfSightDistance) || HasLineOfSight(scanNodeProperties, localPlayer)) && IsScanNodeValid(scanNodeProperties))
				{
					currentScanNodeCount++;
					if (currentScanNodeCount > ConfigManager.scanNodesHardLimit.Value)
					{
						GoodItemScan.LogDebug($"Hard Limit of {ConfigManager.scanNodesHardLimit.Value} reached!");
						break;
					}
					((MonoBehaviour)localPlayer).StartCoroutine(AddScanNodeToUI(scanNodeProperties, viewPoint, currentScanNodeCount));
				}
			}
		}

		private static bool HasLineOfSight(ScanNodeProperties scanNodeProperties, PlayerControllerB localPlayer)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: 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_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: 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_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			if (!scanNodeProperties.requiresLineOfSight)
			{
				return true;
			}
			if (!TryGetOrAddBoxCollider(scanNodeProperties, out BoxCollider boxCollider))
			{
				return false;
			}
			Vector3 cameraPosition = ((Component)localPlayer.gameplayCamera).transform.position;
			Bounds bounds = ((Collider)boxCollider).bounds;
			Vector3 min = ((Bounds)(ref bounds)).min;
			bounds = ((Collider)boxCollider).bounds;
			Vector3 max = ((Bounds)(ref bounds)).max;
			Vector3[] source = (Vector3[])(object)new Vector3[8]
			{
				max,
				new Vector3(max.x, max.y, min.z),
				new Vector3(max.x, min.y, max.z),
				new Vector3(max.x, min.y, min.z),
				new Vector3(min.x, max.y, max.z),
				new Vector3(min.x, max.y, min.z),
				new Vector3(min.x, min.y, max.z),
				min
			};
			return source.Any((Vector3 corner) => !Physics.Linecast(cameraPosition, corner, 256, (QueryTriggerInteraction)1));
		}

		private static bool TryGetOrAddBoxCollider(ScanNodeProperties scanNodeProperties, out BoxCollider boxCollider)
		{
			if (((Component)scanNodeProperties).TryGetComponent<BoxCollider>(ref boxCollider))
			{
				return true;
			}
			GoodItemScan.Logger.LogError((object)(scanNodeProperties.headerText + " has no BoxCollider!"));
			if (!ConfigManager.addBoxCollidersToInvalidScanNodes.Value)
			{
				return false;
			}
			GoodItemScan.Logger.LogError((object)"Adding a BoxCollider!");
			boxCollider = ((Component)scanNodeProperties).gameObject.AddComponent<BoxCollider>();
			return true;
		}

		private static bool IsScanNodeValid(GrabbableObject? grabbableObject, EnemyAI? enemyAI, TerminalAccessibleObject? terminalAccessibleObject)
		{
			if ((Object)(object)grabbableObject != (Object)null && (grabbableObject.isHeld || grabbableObject.isHeldByEnemy || grabbableObject.deactivated))
			{
				return false;
			}
			if (enemyAI != null && enemyAI.isEnemyDead)
			{
				return false;
			}
			if (ConfigManager.showOpenedBlastDoorScanNode.Value)
			{
				return true;
			}
			if (terminalAccessibleObject == null || !terminalAccessibleObject.isBigDoor)
			{
				return true;
			}
			return terminalAccessibleObject != null && !terminalAccessibleObject.isDoorOpen && terminalAccessibleObject.isPoweredOn;
		}

		private bool IsScanNodeValid(ScannedNode scannedNode)
		{
			GameObject scanNodeParent = scannedNode.scanNodeParent;
			return IsScanNodeValid(scanNodeParent);
		}

		private bool IsScanNodeValid(ScanNodeProperties scanNodeProperties)
		{
			GameObject gameObject = ((Component)((Component)scanNodeProperties).transform.parent).gameObject;
			return IsScanNodeValid(gameObject);
		}

		private bool IsScanNodeValid(GameObject parent)
		{
			if (!Object.op_Implicit((Object)(object)parent) || (Object)(object)parent == (Object)null)
			{
				return false;
			}
			GetComponents(parent, out (GrabbableObject, EnemyAI, TerminalAccessibleObject) cachedComponents);
			var (grabbableObject, enemyAI, terminalAccessibleObject) = cachedComponents;
			return IsScanNodeValid(grabbableObject, enemyAI, terminalAccessibleObject);
		}

		private void GetComponents(GameObject parent, out (GrabbableObject?, EnemyAI?, TerminalAccessibleObject?) cachedComponents)
		{
			if (!ConfigManager.useDictionaryCache.Value)
			{
				GetUncachedComponents(parent, out cachedComponents);
			}
			else if (!_componentCache.TryGetValue(parent, out cachedComponents))
			{
				GetUncachedComponents(parent, out cachedComponents);
				_componentCache[parent] = cachedComponents;
			}
		}

		private static void GetUncachedComponents(GameObject parent, out (GrabbableObject?, EnemyAI?, TerminalAccessibleObject?) cachedComponents)
		{
			GrabbableObject val = default(GrabbableObject);
			bool flag = parent.TryGetComponent<GrabbableObject>(ref val);
			EnemyAI val2 = default(EnemyAI);
			bool flag2 = parent.TryGetComponent<EnemyAI>(ref val2);
			TerminalAccessibleObject val3 = default(TerminalAccessibleObject);
			bool flag3 = parent.TryGetComponent<TerminalAccessibleObject>(ref val3);
			cachedComponents = (flag ? val : null, flag2 ? val2 : null, flag3 ? val3 : null);
		}

		private IEnumerator AddScanNodeToUI(ScanNodeProperties scanNodeProperties, Vector3 viewPoint, int currentScanNodeCount)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			yield return (object)new WaitForSeconds(ConfigManager.scanNodeDelay.Value / 100f * (float)currentScanNodeCount);
			yield return null;
			PlayerControllerB localPlayer = StartOfRound.Instance.localPlayerController;
			if ((Object)(object)localPlayer == (Object)null)
			{
				yield break;
			}
			HUDManager hudManager = HUDManager.Instance;
			if (!((Object)(object)hudManager == (Object)null) && !((Object)(object)scanNodeProperties == (Object)null))
			{
				GoodItemScan.LogDebug($"Scanning node '{currentScanNodeCount}'!");
				ScannedNode scannedNode = AssignNodeToUIElement(scanNodeProperties);
				if (scannedNode != null)
				{
					scannedNode.viewPoint = viewPoint;
					ActivateScanElement(hudManager, scannedNode);
				}
			}
		}

		public ScannedNode? AssignNodeToUIElement(ScanNodeProperties node)
		{
			HUDManager instance = HUDManager.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				return null;
			}
			if (_scanNodes.ContainsKey(node))
			{
				return null;
			}
			ScannedNode result = null;
			using (IEnumerator<ScannedNode> enumerator = _scannedNodes.Where((ScannedNode scannedNode) => !scannedNode.hasScanNode).GetEnumerator())
			{
				if (enumerator.MoveNext())
				{
					ScannedNode current = enumerator.Current;
					current.ScanNodeProperties = node;
					result = current;
					_scanNodes.Add(node, current.index);
				}
			}
			return result;
		}

		public bool IsScanNodeVisible(ScannedNode scannedNode)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			ScanNodeProperties scanNodeProperties = scannedNode.ScanNodeProperties;
			if ((Object)(object)scanNodeProperties == (Object)null)
			{
				return false;
			}
			PlayerControllerB localPlayerController = StartOfRound.Instance.localPlayerController;
			Vector3 viewPoint = scannedNode.viewPoint;
			float x = viewPoint.x;
			if (x >= 0f && x <= 1f)
			{
				float y = viewPoint.y;
				if (y >= 0f && y <= 1f)
				{
					float z = viewPoint.z;
					if (z > (float)(scanNodeProperties.maxRange + ((scanNodeProperties.nodeType == 1) ? CheatsAPI.additionalEnemyDistance : CheatsAPI.additionalDistance)))
					{
						return false;
					}
					if (z < (float)scanNodeProperties.minRange)
					{
						return false;
					}
					if (!IsScanNodeValid(scannedNode))
					{
						return false;
					}
					return !ConfigManager.alwaysCheckForLineOfSight.Value || z <= (float)CheatsAPI.noLineOfSightDistance || HasLineOfSight(scanNodeProperties, localPlayerController);
				}
			}
			return false;
		}

		public bool IsScanNodeOnScreen(ScanNodeProperties node, Vector3 scanNodePosition)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			if (!((Component)node).gameObject.activeSelf)
			{
				return false;
			}
			PlayerControllerB localPlayerController = StartOfRound.Instance.localPlayerController;
			if ((Object)(object)localPlayerController == (Object)null)
			{
				return false;
			}
			Camera gameplayCamera = localPlayerController.gameplayCamera;
			Vector3 val = scanNodePosition - ((Component)gameplayCamera).transform.position;
			((Vector3)(ref val)).Normalize();
			float cosHalfAdjustedFov = GetCosHalfAdjustedFov(gameplayCamera);
			return Vector3.Dot(val, ((Component)gameplayCamera).transform.forward) >= cosHalfAdjustedFov;
		}

		private float GetCosHalfAdjustedFov(Camera camera)
		{
			if (_cachedFovValues.TryGetValue(camera, out var value))
			{
				return value;
			}
			float aspect = camera.aspect;
			float num = 0.5f + aspect / 100f;
			float num2 = Mathf.Atan(Mathf.Tan(camera.fieldOfView * num * (MathF.PI / 180f)) / aspect) * 57.29578f * 2f;
			value = Mathf.Cos(num2 * (MathF.PI / 180f));
			_cachedFovValues[camera] = value;
			return value;
		}

		public void UpdateScanNodes()
		{
			HUDManager instance = HUDManager.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			foreach (ScanNodeProperties item in _scanNodesToRemove)
			{
				_scanNodes.Remove(item);
			}
			_scanNodesToRemove.Clear();
			UpdateScrapTotalValue(instance);
			if (_scanNodes.Count <= 0)
			{
				return;
			}
			_updateTimer -= Time.deltaTime;
			if (_updateTimer > 0f)
			{
				return;
			}
			_updateTimer = ConfigManager.updateTimer.Value / 100f;
			bool flag = _nodeVisibilityCheckCoroutine == null;
			foreach (KeyValuePair<ScanNodeProperties, int> scanNode in _scanNodes)
			{
				scanNode.Deconstruct(out var key, out var value);
				ScanNodeProperties val = key;
				int index = value;
				ScannedNode scannedNode = _scannedNodes[index];
				if ((Object)(object)val == (Object)null || !Object.op_Implicit((Object)(object)val))
				{
					HandleMissingNode(scannedNode);
					continue;
				}
				if (flag)
				{
					_scanNodesToUpdate.Add(scannedNode);
				}
				UpdateScanNodePosition(scannedNode);
			}
			if (flag && _scanNodesToUpdate.Count > 0)
			{
				_nodeVisibilityCheckCoroutine = ((MonoBehaviour)HUDManager.Instance).StartCoroutine(UpdateScanNodesRoutine());
			}
		}

		private IEnumerator UpdateScanNodesRoutine()
		{
			yield return null;
			int processedNodesThisFrame = 0;
			foreach (ScannedNode scannedNode in _scanNodesToUpdate)
			{
				if (processedNodesThisFrame >= ConfigManager.maxScanNodesToProcessPerFrame.Value)
				{
					yield return null;
					processedNodesThisFrame = 0;
				}
				processedNodesThisFrame++;
				if (!IsScanNodeVisible(scannedNode))
				{
					HandleMissingNode(scannedNode);
				}
				else
				{
					if (!ConfigManager.updateScanNodeText.Value)
					{
						continue;
					}
					ScanNodeProperties node = scannedNode.ScanNodeProperties;
					if (!((Object)(object)node == (Object)null))
					{
						((TMP_Text)scannedNode.header).text = node.headerText;
						((TMP_Text)scannedNode.footer).text = node.subText;
						if (ConfigManager.hideEmptyScanNodeSubText.Value)
						{
							scannedNode.subTextBox.SetActive(!string.IsNullOrWhiteSpace(node.subText));
						}
					}
				}
			}
			_scanNodesToUpdate.Clear();
			_nodeVisibilityCheckCoroutine = null;
		}

		private void HandleMissingNode(ScannedNode scannedNode)
		{
			if (scannedNode != null)
			{
				ScanNodeProperties scanNodeProperties = scannedNode.ScanNodeProperties;
				if ((Object)(object)scanNodeProperties != (Object)null)
				{
					_scanNodesToRemove.Add(scanNodeProperties);
				}
				scannedNode.ScanNodeProperties = null;
				((Component)scannedNode.rectTransform).gameObject.SetActive(false);
				if (!((Object)(object)scanNodeProperties == (Object)null) && scanNodeProperties.nodeType == 2 && scanNodeProperties.scrapValue > 0)
				{
					_scrapScannedAmount--;
					_scrapScannedValue = Mathf.Clamp(_scrapScannedValue - scanNodeProperties.scrapValue, 0, 10000);
				}
			}
		}

		private void ActivateScanElement(HUDManager hudManager, ScannedNode scannedNode)
		{
			ScanNodeProperties scanNodeProperties = scannedNode.ScanNodeProperties;
			if ((Object)(object)scanNodeProperties == (Object)null)
			{
				return;
			}
			if (scanNodeProperties != null && scanNodeProperties.nodeType == 2 && scanNodeProperties.scrapValue > 0)
			{
				_scrapScannedAmount++;
				_scrapScannedValue += scanNodeProperties.scrapValue;
			}
			RectTransform rectTransform = scannedNode.rectTransform;
			if (!((Component)rectTransform).gameObject.activeSelf)
			{
				((Component)rectTransform).gameObject.SetActive(true);
				Animator val = default(Animator);
				if (((Component)rectTransform).TryGetComponent<Animator>(ref val))
				{
					val.SetInteger(_ColorNumberAnimatorHash, scanNodeProperties.nodeType);
				}
				((TMP_Text)scannedNode.header).text = scanNodeProperties.headerText;
				((TMP_Text)scannedNode.footer).text = scanNodeProperties.subText;
				if (scanNodeProperties.creatureScanID != -1)
				{
					hudManager.AttemptScanNewCreature(scanNodeProperties.creatureScanID);
				}
				if (ConfigManager.hideEmptyScanNodeSubText.Value)
				{
					scannedNode.subTextBox.SetActive(!string.IsNullOrWhiteSpace(scanNodeProperties.subText));
				}
			}
		}

		private void UpdateScanNodePosition(ScannedNode scannedNode)
		{
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			RectTransform rectTransform = scannedNode.rectTransform;
			ScanNodeProperties scanNodeProperties = scannedNode.ScanNodeProperties;
			if (!((Object)(object)scanNodeProperties == (Object)null) && Object.op_Implicit((Object)(object)scanNodeProperties))
			{
				if (!Object.op_Implicit((Object)(object)_screenRectTransform))
				{
					GameObject gameObject = ((Component)HUDManager.Instance.playerScreenShakeAnimator).gameObject;
					_screenRectTransform = gameObject.GetComponent<RectTransform>();
				}
				Rect rect = _screenRectTransform.rect;
				Vector3 position = ((Component)scanNodeProperties).transform.position;
				Vector3 val = (scannedNode.viewPoint = GameNetworkManager.Instance.localPlayerController.gameplayCamera.WorldToViewportPoint(position));
				Vector3 val2 = default(Vector3);
				((Vector3)(ref val2))..ctor(((Rect)(ref rect)).xMin + ((Rect)(ref rect)).width * val.x, ((Rect)(ref rect)).yMin + ((Rect)(ref rect)).height * val.y, val.z);
				rectTransform.anchoredPosition = Vector2.op_Implicit(val2);
			}
		}

		private void UpdateScrapTotalValue(HUDManager hudManager)
		{
			if (_scrapScannedAmount <= 0 || _scanNodes.Count <= 0)
			{
				((TMP_Text)hudManager.totalValueText).text = "$0";
				_scrapScannedAmount = 0;
				_scrapScannedValue = 0;
				_scrapScannedValueDisplayed = 0;
				_addToDisplayTotalInterval = 0.35f;
				hudManager.scanInfoAnimator.SetBool(_DisplayAnimatorHash, false);
				return;
			}
			hudManager.scanInfoAnimator.SetBool(_DisplayAnimatorHash, _scrapScannedValue != 0);
			if (_scrapScannedValueDisplayed >= _scrapScannedValue || _scrapScannedValueDisplayed >= 10000)
			{
				return;
			}
			_addToDisplayTotalInterval -= Time.deltaTime;
			if (!(_addToDisplayTotalInterval > 0f))
			{
				_addToDisplayTotalInterval = 0.08525f * ((float)ConfigManager.totalAddWaitMultiplier.Value / 100f);
				_scrapScannedValueDisplayed = (int)Mathf.Clamp(Mathf.MoveTowards((float)_scrapScannedValueDisplayed, (float)_scrapScannedValue, (1500f + (float)(_scrapScannedValue * ConfigManager.totalAddWaitMultiplier.Value) / 100f) * Time.deltaTime), 0f, 10000f);
				((TMP_Text)hudManager.totalValueText).text = $"${_scrapScannedValueDisplayed}";
				if (_scrapScannedValueDisplayed < _scrapScannedValue && _scrapScannedValueDisplayed < 10000)
				{
					hudManager.UIAudio.PlayOneShot(hudManager.addToScrapTotalSFX);
				}
				else
				{
					hudManager.UIAudio.PlayOneShot(hudManager.finishAddingToTotalSFX);
				}
			}
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "TestAccount666.GoodItemScan";

		public const string PLUGIN_NAME = "GoodItemScan";

		public const string PLUGIN_VERSION = "1.10.0";
	}
}
namespace GoodItemScan.Patches
{
	[HarmonyPatch(typeof(HUDManager))]
	public static class HUDManagerPatch
	{
		internal static void InitMonoMod()
		{
			//IL_0039: 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_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Expected O, but got Unknown
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Expected O, but got Unknown
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Expected O, but got Unknown
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Expected O, but got Unknown
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Expected O, but got Unknown
			GoodItemScan.Hooks.Add(new Hook((MethodBase)AccessTools.Method(typeof(HUDManager), "AssignNodeToUIElement", (Type[])null, (Type[])null), (Delegate)new Action<Action<HUDManager, ScanNodeProperties>, HUDManager, ScanNodeProperties>(DontAssignNodeToUIElement), new HookConfig
			{
				Priority = -99
			}));
			GoodItemScan.Hooks.Add(new Hook((MethodBase)AccessTools.Method(typeof(HUDManager), "AssignNewNodes", (Type[])null, (Type[])null), (Delegate)new Action<Action<HUDManager, PlayerControllerB>, HUDManager, PlayerControllerB>(DontAssignNewNodes), new HookConfig
			{
				Priority = -99
			}));
			GoodItemScan.Hooks.Add(new Hook((MethodBase)AccessTools.Method(typeof(HUDManager), "MeetsScanNodeRequirements", (Type[])null, (Type[])null), (Delegate)new Func<Func<HUDManager, ScanNodeProperties, PlayerControllerB, bool>, HUDManager, ScanNodeProperties, PlayerControllerB, bool>(MeetsScanNodeRequirements), new HookConfig
			{
				Priority = -99
			}));
			GoodItemScan.Hooks.Add(new Hook((MethodBase)AccessTools.Method(typeof(HUDManager), "NodeIsNotVisible", (Type[])null, (Type[])null), (Delegate)new Func<Func<HUDManager, ScanNodeProperties, int, bool>, HUDManager, ScanNodeProperties, int, bool>(NodeIsAlwaysVisible), new HookConfig
			{
				Priority = -99
			}));
			GoodItemScan.Hooks.Add(new Hook((MethodBase)AccessTools.Method(typeof(HUDManager), "UpdateScanNodes", (Type[])null, (Type[])null), (Delegate)new Action<Action<HUDManager, PlayerControllerB>, HUDManager, PlayerControllerB>(UpdateScanNodes), new HookConfig
			{
				Priority = -99
			}));
		}

		private static void DontAssignNodeToUIElement(Action<HUDManager, ScanNodeProperties> orig, HUDManager self, ScanNodeProperties node)
		{
		}

		private static void DontAssignNewNodes(Action<HUDManager, PlayerControllerB> orig, HUDManager self, PlayerControllerB playerScript)
		{
		}

		private static bool MeetsScanNodeRequirements(Func<HUDManager, ScanNodeProperties, PlayerControllerB, bool> orig, HUDManager self, ScanNodeProperties node, PlayerControllerB playerScript)
		{
			return true;
		}

		private static bool NodeIsAlwaysVisible(Func<HUDManager, ScanNodeProperties, int, bool> orig, HUDManager self, ScanNodeProperties node, int elementIndex)
		{
			return false;
		}

		private static void UpdateScanNodes(Action<HUDManager, PlayerControllerB> orig, HUDManager self, PlayerControllerB playerScript)
		{
			GoodItemScan.scanner?.UpdateScanNodes();
		}

		[HarmonyPatch("DisableAllScanElements")]
		[HarmonyPrefix]
		private static bool RedirectDisableAllScanElements()
		{
			GoodItemScan.scanner?.DisableAllScanElements();
			return false;
		}

		[HarmonyPatch("PingScan_performed")]
		[HarmonyPrefix]
		private static bool PingScanPerformed(ref CallbackContext context)
		{
			if (!((CallbackContext)(ref context)).performed)
			{
				return false;
			}
			GoodItemScan.scanner?.Scan();
			return false;
		}

		[HarmonyPatch("Start")]
		[HarmonyPostfix]
		private static void AfterHudManagerAwake(HUDManager __instance)
		{
			GoodItemScan.scanner = new Scanner();
			GoodItemScan.SetIncreasedMaximumScanNodes(__instance);
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}