Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of GoodItemScan v2.0.3
GoodItemScan.dll
Decompiled 2 weeks agousing System; using System.Collections; using System.Collections.Generic; 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 TestAccountCore.KotlinSharp.Extensions; 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("com.olegknyazev.softmask")] [assembly: IgnoresAccessChecksTo("DissonanceVoip")] [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("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("2.0.3.0")] [assembly: AssemblyInformationalVersion("2.0.3+cf7d66f109e580937480b9b07ef002f2c6e9f201")] [assembly: AssemblyProduct("GoodItemScan")] [assembly: AssemblyTitle("TestAccount666.GoodItemScan")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("2.0.3.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 class ComponentCache { private readonly Dictionary<GameObject, (GrabbableObject? Grabbable, EnemyAI? Enemy, TerminalAccessibleObject? Terminal)> _cache = new Dictionary<GameObject, (GrabbableObject, EnemyAI, TerminalAccessibleObject)>(); public void Clear() { _cache.Clear(); } public (GrabbableObject? Grabbable, EnemyAI? Enemy, TerminalAccessibleObject? Terminal) GetComponents(GameObject parent) { GameObject parent2 = parent; if (!ConfigManager.useDictionaryCache.Value) { return GetUncachedComponents(parent2); } if (_cache.TryGetValue(parent2, out (GrabbableObject, EnemyAI, TerminalAccessibleObject) value)) { return value; } return KotlinStyleExtensions.Also<(GrabbableObject, EnemyAI, TerminalAccessibleObject)>(GetUncachedComponents(parent2), (Action<(GrabbableObject, EnemyAI, TerminalAccessibleObject)>)delegate((GrabbableObject Grabbable, EnemyAI Enemy, TerminalAccessibleObject Terminal) tuple) { _cache[parent2] = tuple; }); } private static (GrabbableObject? Grabbable, EnemyAI? Enemy, TerminalAccessibleObject? Terminal) GetUncachedComponents(GameObject parent) { GrabbableObject item = default(GrabbableObject); parent.TryGetComponent<GrabbableObject>(ref item); EnemyAI item2 = default(EnemyAI); parent.TryGetComponent<EnemyAI>(ref item2); TerminalAccessibleObject item3 = default(TerminalAccessibleObject); parent.TryGetComponent<TerminalAccessibleObject>(ref item3); return (item, item2, item3); } } public static class ConfigManager { public static ConfigEntry<bool> holdToScan; 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> calculateDistance; 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; public static ConfigEntry<bool> fixLandmineScanNode; 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_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Expected O, but got Unknown //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_020b: 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", 60, 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."); calculateDistance = configFile.Bind<bool>("General", "Calculate Distance", false, "If true, will perform additional distance calculations. If false, use viewport as distance. Set to `true`, if you don't mind slightly worse performance and want accurate distance calculations."); 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", 0.6f, 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>())); fixLandmineScanNode = configFile.Bind<bool>("Special Cases", "Fix Landmine ScanNode", true, "Fixes Landmines being scannable after exploding."); holdToScan = configFile.Bind<bool>("General", "Hold To Scan", false, "If true, holding the scan button will continuously scan."); } } [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency("TestAccount666.TestAccountCore", "1.18.0")] [BepInPlugin("TestAccount666.GoodItemScan", "GoodItemScan", "2.0.3")] 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 v2.0.3 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; } Patch[] array = patchInfo.Postfixes.ToArray(); foreach (Patch val in array) { 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 Animator animator = null; public Vector3 viewPoint; public Vector2 lastKnownPosition = Vector2.zero; public GameObject scanNodeParent = null; public readonly int canvasIndex; public readonly RectTransform rectTransform; public readonly TextMeshProUGUI header; public readonly TextMeshProUGUI footer; public readonly GameObject subTextBox; public ScanNodeProperties ScanNodeProperties { get { return _scanNodeProperties ?? null; } set { _scanNodeProperties = value; if ((Object)(object)value != (Object)null && Object.op_Implicit((Object)(object)value)) { scanNodeParent = ((Component)((Component)value).transform.parent).gameObject; } } } public bool HasScanNode => (Object)(object)_scanNodeProperties != (Object)null && Object.op_Implicit((Object)(object)_scanNodeProperties); public ScannedNode(RectTransform rectTransform, TextMeshProUGUI header, TextMeshProUGUI footer, GameObject subTextBox, int canvasIndex) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) this.canvasIndex = canvasIndex; this.rectTransform = rectTransform; this.header = header; this.footer = footer; this.subTextBox = subTextBox; base..ctor(); } } public class Scanner { [CompilerGenerated] private sealed class <>c__DisplayClass20_0 { public Vector3 playerPos; internal float <ScanNodesRoutine>b__0(ScanNodeProperties node) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) return Vector3.Distance(playerPos, ((Component)node).transform.position); } } [CompilerGenerated] private sealed class <>c__DisplayClass21_0 { public Vector3 viewPoint; public Scanner <>4__this; public HUDManager hudManager; internal void <AddScanNodeToUI>b__0(ScannedNode scannedNode) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) scannedNode.viewPoint = viewPoint; <>4__this.RefreshPositionCache(); <>4__this.UpdateScanNodePosition(scannedNode, snap: true); <>4__this.ActivateScanElement(hudManager, scannedNode); } } [CompilerGenerated] private sealed class <AddScanNodeToUI>d__21 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public ScanNodeProperties node; public Vector3 viewPoint; public int currentScanNodeCount; public Scanner <>4__this; private <>c__DisplayClass21_0 <>8__1; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <AddScanNodeToUI>d__21(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>8__1 = null; <>1__state = -2; } private bool MoveNext() { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>8__1 = new <>c__DisplayClass21_0(); <>8__1.viewPoint = viewPoint; <>8__1.<>4__this = <>4__this; <>2__current = (object)new WaitForSeconds(ConfigManager.scanNodeDelay.Value / 100f * (float)currentScanNodeCount); <>1__state = 1; return true; case 1: <>1__state = -1; <>2__current = null; <>1__state = 2; return true; case 2: { <>1__state = -1; <>8__1.hudManager = HUDManager.Instance; if ((Object)(object)<>8__1.hudManager == (Object)null || (Object)(object)node == (Object)null || !Object.op_Implicit((Object)(object)node)) { return false; } GoodItemScan.LogDebug($"Scanning node '{currentScanNodeCount}'! ({node.headerText};{node.subText})"); ScannedNode? scannedNode2 = <>4__this.AssignNodeToUIElement(node); if (scannedNode2 != null) { KotlinStyleExtensions.Also<ScannedNode>(scannedNode2, (Action<ScannedNode>)delegate(ScannedNode scannedNode) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) scannedNode.viewPoint = <>8__1.viewPoint; <>8__1.<>4__this.RefreshPositionCache(); <>8__1.<>4__this.UpdateScanNodePosition(scannedNode, snap: true); <>8__1.<>4__this.ActivateScanElement(<>8__1.hudManager, scannedNode); }); } return false; } } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <ScanNodesRoutine>d__20 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public PlayerControllerB localPlayer; public ScanNodeProperties[] scanNodes; public Scanner <>4__this; private int <currentScanNodeCount>5__1; private int <processedNodesThisFrame>5__2; private int <maxPerFrame>5__3; private int <hardLimit>5__4; private <>c__DisplayClass20_0 <>8__5; private ScanNodeProperties[] <>s__6; private int <>s__7; private ScanNodeProperties <node>5__8; private Vector3 <viewPoint>5__9; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <ScanNodesRoutine>d__20(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>8__5 = null; <>s__6 = null; <node>5__8 = null; <>1__state = -2; } private bool MoveNext() { //IL_0070: 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_018a: Unknown result type (might be due to invalid IL or missing references) //IL_018f: 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_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_0218: Unknown result type (might be due to invalid IL or missing references) switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = null; <>1__state = 1; return true; case 1: <>1__state = -1; if (ConfigManager.preferClosestNodes.Value) { <>8__5 = new <>c__DisplayClass20_0(); <>8__5.playerPos = ((Component)localPlayer).transform.position; scanNodes = scanNodes.OrderBy((ScanNodeProperties node) => Vector3.Distance(<>8__5.playerPos, ((Component)node).transform.position)).ToArray(); <>8__5 = null; } <currentScanNodeCount>5__1 = 0; <processedNodesThisFrame>5__2 = 0; <maxPerFrame>5__3 = ConfigManager.maxScanNodesToProcessPerFrame.Value; <hardLimit>5__4 = ConfigManager.scanNodesHardLimit.Value; <>s__6 = scanNodes; <>s__7 = 0; goto IL_0244; case 2: { <>1__state = -1; <processedNodesThisFrame>5__2 = 0; goto IL_0161; } IL_0236: <>s__7++; goto IL_0244; IL_0244: if (<>s__7 < <>s__6.Length) { <node>5__8 = <>s__6[<>s__7]; if ((Object)(object)<node>5__8 == (Object)null || !Object.op_Implicit((Object)(object)<node>5__8)) { goto IL_0236; } if (<processedNodesThisFrame>5__2 >= <maxPerFrame>5__3) { <>2__current = null; <>1__state = 2; return true; } goto IL_0161; } <>s__6 = null; return false; IL_0161: <processedNodesThisFrame>5__2++; <viewPoint>5__9 = localPlayer.gameplayCamera.WorldToViewportPoint(((Component)<node>5__8).transform.position); if (ScanValidator.IsNodeVisible(<node>5__8, <viewPoint>5__9, forceCheckLos: true, <>4__this._componentCache)) { <currentScanNodeCount>5__1++; if (<currentScanNodeCount>5__1 > <hardLimit>5__4) { GoodItemScan.LogDebug($"Hard Limit of {<hardLimit>5__4} reached!"); return false; } ((MonoBehaviour)localPlayer).StartCoroutine(<>4__this.AddScanNodeToUI(<node>5__8, <viewPoint>5__9, <currentScanNodeCount>5__1)); <node>5__8 = null; } goto IL_0236; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <UpdateScanNodesRoutine>d__25 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public Scanner <>4__this; private IEnumerator<HashSet<ScannedNode>> <>s__1; private HashSet<ScannedNode> <set>5__2; private HashSet<ScannedNode>.Enumerator <>s__3; private ScannedNode <scannedNode>5__4; private ScanNodeProperties <node>5__5; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <UpdateScanNodesRoutine>d__25(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || (uint)(num - 2) <= 1u) { try { } finally { <>m__Finally1(); } } <>s__1 = null; <set>5__2 = null; <>s__3 = default(HashSet<ScannedNode>.Enumerator); <scannedNode>5__4 = null; <node>5__5 = null; <>1__state = -2; } private bool MoveNext() { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown //IL_0272: Unknown result type (might be due to invalid IL or missing references) //IL_027c: Expected O, but got Unknown //IL_0114: Unknown result type (might be due to invalid IL or missing references) try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForEndOfFrame(); <>1__state = 1; return true; case 1: <>1__state = -1; <>s__1 = <>4__this._ui.canvasesToUpdate.Where((HashSet<ScannedNode> set) => set.Count > 0).GetEnumerator(); <>1__state = -3; break; case 2: <>1__state = -3; <>2__current = (object)new WaitForEndOfFrame(); <>1__state = 3; return true; case 3: <>1__state = -3; <set>5__2 = null; break; } if (<>s__1.MoveNext()) { <set>5__2 = <>s__1.Current; <>4__this.RefreshPositionCache(); <>s__3 = <set>5__2.GetEnumerator(); try { while (<>s__3.MoveNext()) { <scannedNode>5__4 = <>s__3.Current; <>4__this.UpdateScanNodePosition(<scannedNode>5__4); if (!ScanValidator.IsNodeVisible(<scannedNode>5__4.ScanNodeProperties, <scannedNode>5__4.viewPoint, forceCheckLos: false, <>4__this._componentCache)) { <>4__this.HandleMissingNode(<scannedNode>5__4); } else { if (!ConfigManager.updateScanNodeText.Value) { continue; } <node>5__5 = <scannedNode>5__4.ScanNodeProperties; if (!((Object)(object)<node>5__5 == (Object)null) && Object.op_Implicit((Object)(object)<node>5__5)) { ((TMP_Text)<scannedNode>5__4.header).text = <node>5__5.headerText; ((TMP_Text)<scannedNode>5__4.footer).text = <node>5__5.subText; if (ConfigManager.hideEmptyScanNodeSubText.Value) { <scannedNode>5__4.subTextBox.SetActive(!string.IsNullOrWhiteSpace(<node>5__5.subText)); <node>5__5 = null; <scannedNode>5__4 = null; } } } } } finally { ((IDisposable)<>s__3).Dispose(); } <>s__3 = default(HashSet<ScannedNode>.Enumerator); <set>5__2.Clear(); <>2__current = null; <>1__state = 2; return true; } <>m__Finally1(); <>s__1 = null; <>4__this._nodeVisibilityCheckCoroutine = null; return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<>s__1 != null) { <>s__1.Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private static readonly int _COLOR_NUMBER_ANIMATOR_HASH = Animator.StringToHash("colorNumber"); public static readonly int DISPLAY_ANIMATOR_HASH = Animator.StringToHash("display"); private static readonly int _SCAN_ANIMATOR_HASH = Animator.StringToHash("scan"); private Coroutine? _scanCoroutine; private Coroutine? _nodeVisibilityCheckCoroutine; private readonly List<ScannedNode> _scannedNodesToRemove = new List<ScannedNode>(); public readonly HashSet<ScannedNode> activeNodes = new HashSet<ScannedNode>(); private readonly ComponentCache _componentCache = new ComponentCache(); private readonly ScrapTracker _scrapTracker = new ScrapTracker(); private readonly ScannerUI _ui = new ScannerUI(); private float _updateTimer = 0.05f; private Rect _cachedScreenRect; private Camera? _cachedCamera; private RectTransform _screenRectTransform = null; private RectTransform ScreenRectTransform { get { if (Object.op_Implicit((Object)(object)_screenRectTransform)) { return _screenRectTransform; } HUDManager instance = HUDManager.Instance; if ((Object)(object)instance == (Object)null || !Object.op_Implicit((Object)(object)instance)) { return null; } GameObject gameObject = ((Component)instance.playerScreenShakeAnimator).gameObject; return _screenRectTransform = gameObject.GetComponent<RectTransform>(); } } public void FillInScanNodes(RectTransform originalRect) { DisableAllScanElements(); _componentCache.Clear(); _ui.Initialize(originalRect); _nodeVisibilityCheckCoroutine = null; } public void Scan() { //IL_008b: Unknown result type (might be due to invalid IL or missing references) PlayerControllerB localPlayerController = StartOfRound.Instance.localPlayerController; if (!((Object)(object)localPlayerController == (Object)null) && Object.op_Implicit((Object)(object)localPlayerController)) { HUDManager instance = HUDManager.Instance; if (!((Object)(object)instance == (Object)null) && Object.op_Implicit((Object)(object)instance) && instance.CanPlayerScan() && !((double)instance.playerPingingScan > -1.0)) { ResetScanState(instance); Transform transform = ((Component)localPlayerController.gameplayCamera).transform; ((Component)instance.scanEffectAnimator).transform.position = transform.position; instance.scanEffectAnimator.SetTrigger(_SCAN_ANIMATOR_HASH); instance.UIAudio.PlayOneShot(instance.scanSFX); GoodItemScan.LogDebug("Scan Initiated!"); ScanNodeProperties[] array = Object.FindObjectsByType<ScanNodeProperties>((FindObjectsInactive)0, (FindObjectsSortMode)0); GoodItemScan.LogDebug($"Got '{array.Length}' nodes!"); _scanCoroutine = ((MonoBehaviour)instance).StartCoroutine(ScanNodesRoutine(localPlayerController, array)); } } } private void ResetScanState(HUDManager hudManager) { if (_scanCoroutine != null) { ((MonoBehaviour)hudManager).StopCoroutine(_scanCoroutine); } if (ConfigManager.alwaysRescan.Value) { DisableAllScanElements(); _scrapTracker.Reset(); } hudManager.playerPingingScan = 0.3f; } public void DisableAllScanElements() { KotlinStyleExtensions.ForEach<ScannedNode>((IEnumerable<ScannedNode>)activeNodes.ToHashSet(), (Action<ScannedNode>)DisableScanNode); _scannedNodesToRemove.Clear(); _ui.ClearUpdateSets(); HUDManager instance = HUDManager.Instance; if (_nodeVisibilityCheckCoroutine != null && (Object)(object)instance != (Object)null) { ((MonoBehaviour)instance).StopCoroutine(_nodeVisibilityCheckCoroutine); } _nodeVisibilityCheckCoroutine = null; } [IteratorStateMachine(typeof(<ScanNodesRoutine>d__20))] private IEnumerator ScanNodesRoutine(PlayerControllerB localPlayer, ScanNodeProperties[] scanNodes) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <ScanNodesRoutine>d__20(0) { <>4__this = this, localPlayer = localPlayer, scanNodes = scanNodes }; } [IteratorStateMachine(typeof(<AddScanNodeToUI>d__21))] private IEnumerator AddScanNodeToUI(ScanNodeProperties node, 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 decompiler failed: Unexpected instruction in Iterator.Dispose() return new <AddScanNodeToUI>d__21(0) { <>4__this = this, node = node, viewPoint = viewPoint, currentScanNodeCount = currentScanNodeCount }; } public ScannedNode? AssignNodeToUIElement(ScanNodeProperties node) { ScanNodeProperties node2 = node; if ((Object)(object)HUDManager.Instance == (Object)null) { return null; } if (activeNodes.Any((ScannedNode active) => (Object)(object)active.ScanNodeProperties == (Object)(object)node2)) { return null; } ScannedNode? scannedNode2 = _ui.DequeueNode(); return (scannedNode2 != null) ? KotlinStyleExtensions.Also<ScannedNode>(scannedNode2, (Action<ScannedNode>)delegate(ScannedNode scannedNode) { scannedNode.ScanNodeProperties = node2; activeNodes.Add(scannedNode); }) : null; } public void UpdateScanNodes() { HUDManager instance = HUDManager.Instance; if ((Object)(object)instance == (Object)null) { return; } HandlePendingRemovals(); _scrapTracker.UpdateDisplay(instance, activeNodes.Count > 0); if (activeNodes.Count <= 0) { return; } _updateTimer -= Time.deltaTime; if (_updateTimer > 0f) { return; } _updateTimer = ConfigManager.updateTimer.Value / 100f; if (_nodeVisibilityCheckCoroutine != null) { return; } RefreshPositionCache(); foreach (ScannedNode activeNode in activeNodes) { if (!activeNode.HasScanNode) { HandleMissingNode(activeNode); } else { _ui.canvasesToUpdate[activeNode.canvasIndex].Add(activeNode); } } if (_ui.TotalNodesToUpdate > 0) { _nodeVisibilityCheckCoroutine = ((MonoBehaviour)instance).StartCoroutine(UpdateScanNodesRoutine()); } } private void HandlePendingRemovals() { if (_scannedNodesToRemove.Count > 0) { _scannedNodesToRemove.ForEach(DisableScanNode); _scannedNodesToRemove.Clear(); } } [IteratorStateMachine(typeof(<UpdateScanNodesRoutine>d__25))] private IEnumerator UpdateScanNodesRoutine() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <UpdateScanNodesRoutine>d__25(0) { <>4__this = this }; } private void RefreshPositionCache() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) _cachedScreenRect = ScreenRectTransform.rect; StartOfRound instance = StartOfRound.Instance; if ((Object)(object)instance == (Object)null || !Object.op_Implicit((Object)(object)instance)) { _cachedCamera = null; return; } PlayerControllerB localPlayerController = instance.localPlayerController; if ((Object)(object)localPlayerController == (Object)null || !Object.op_Implicit((Object)(object)localPlayerController)) { _cachedCamera = null; } else { _cachedCamera = localPlayerController.gameplayCamera; } } private void HandleMissingNode(ScannedNode scannedNode) { if (scannedNode != null) { ScanNodeProperties scanNodeProperties = scannedNode.ScanNodeProperties; if ((Object)(object)scanNodeProperties != (Object)null && Object.op_Implicit((Object)(object)scanNodeProperties)) { _scrapTracker.RemoveScrap(scanNodeProperties); } _scannedNodesToRemove.Add(scannedNode); } } private void UpdateScanNodePosition(ScannedNode scannedNode, bool snap = false) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_0105: 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_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) ScannedNode scannedNode2 = scannedNode; if ((Object)(object)_cachedCamera == (Object)null) { return; } ScanNodeProperties scanNodeProperties = scannedNode2.ScanNodeProperties; if ((Object)(object)scanNodeProperties == (Object)null || !Object.op_Implicit((Object)(object)scanNodeProperties)) { return; } Vector3 val = KotlinStyleExtensions.Also<Vector3>(_cachedCamera.WorldToViewportPoint(((Component)scanNodeProperties).transform.position), (Action<Vector3>)delegate(Vector3 p) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) scannedNode2.viewPoint = p; }); Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(((Rect)(ref _cachedScreenRect)).xMin + ((Rect)(ref _cachedScreenRect)).width * val.x, ((Rect)(ref _cachedScreenRect)).yMin + ((Rect)(ref _cachedScreenRect)).height * val.y); float num = Vector2.Distance(scannedNode2.lastKnownPosition, val2); if (!((double)num <= 0.01)) { Vector2 val3 = (snap ? val2 : Vector2.Lerp(scannedNode2.lastKnownPosition, val2, Time.deltaTime * (num * 80f))); scannedNode2.rectTransform.anchoredPosition = KotlinStyleExtensions.Also<Vector2>(val3, (Action<Vector2>)delegate(Vector2 p) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) scannedNode2.lastKnownPosition = p; }); } } public void ActivateScanElement(HUDManager hudManager, ScannedNode scannedNode) { ScanNodeProperties scanNodeProperties = scannedNode.ScanNodeProperties; if ((Object)(object)scanNodeProperties == (Object)null || !Object.op_Implicit((Object)(object)scanNodeProperties)) { return; } _scrapTracker.AddScrap(scanNodeProperties); if (!((Component)scannedNode.rectTransform).gameObject.activeSelf) { ((Component)scannedNode.rectTransform).gameObject.SetActive(true); if (((Component)scannedNode.rectTransform).TryGetComponent<Animator>(ref scannedNode.animator)) { scannedNode.animator.SetInteger(_COLOR_NUMBER_ANIMATOR_HASH, 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 DisableScanNode(ScannedNode scannedNode) { if (Object.op_Implicit((Object)(object)scannedNode.rectTransform)) { ((Component)scannedNode.rectTransform).gameObject.SetActive(false); } KotlinStyleExtensions.Also<ScannedNode>(scannedNode, (Action<ScannedNode>)delegate(ScannedNode s) { s.ScanNodeProperties = null; s.animator = null; activeNodes.Remove(s); _ui.EnqueueNode(s); }); } } public class ScannerUI { private readonly List<GameObject> _canvases = new List<GameObject>(); private readonly List<Queue<ScannedNode>> _freeNodes = new List<Queue<ScannedNode>>(); public readonly List<HashSet<ScannedNode>> canvasesToUpdate = new List<HashSet<ScannedNode>>(); public int TotalNodesToUpdate => canvasesToUpdate.Sum((HashSet<ScannedNode> set) => set.Count); public void Clear() { _canvases.ForEach((Action<GameObject>)Object.Destroy); _canvases.Clear(); _freeNodes.Clear(); canvasesToUpdate.Clear(); } public void Initialize(RectTransform originalRect) { //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Expected O, but got Unknown RectTransform originalRect2 = originalRect; Clear(); int value = ConfigManager.scanNodesHardLimit.Value; int value2 = ConfigManager.maxScanNodesToProcessPerFrame.Value; int num = Mathf.CeilToInt((float)value / (float)value2); GoodItemScan.LogDebug($"Built {num} canvases!"); if (num > 6) { GoodItemScan.Logger.LogWarning((object)($"Your max size ({value}) is considerably higher than your maxPerFrame ({value2}) setting! " + "This will cause the scanner to appear laggy! Try maxSize / maxPerFrame to be lower than 6!")); } for (int i = 0; i < num; i++) { canvasesToUpdate.Add(new HashSet<ScannedNode>()); } GameObject obj2 = GameObject.Find("Systems/UI/Canvas"); Canvas parentCanvas = ((obj2 != null) ? obj2.GetComponent<Canvas>() : null); for (int j = 0; j < num; j++) { GameObject val = KotlinStyleExtensions.Also<GameObject>(new GameObject($"ScanCanvas_{j}", new Type[2] { typeof(RectTransform), typeof(Canvas) }), (Action<GameObject>)delegate(GameObject obj) { obj.transform.SetParent(((Transform)originalRect2).parent, false); obj.layer = 5; }); _canvases.Add(val); _freeNodes.Add(new Queue<ScannedNode>()); KotlinStyleExtensions.Also<Canvas>(val.GetComponent<Canvas>(), (Action<Canvas>)delegate(Canvas canvasComp) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)parentCanvas == (Object)null) && Object.op_Implicit((Object)(object)parentCanvas)) { canvasComp.renderMode = parentCanvas.renderMode; canvasComp.worldCamera = parentCanvas.worldCamera; canvasComp.planeDistance = parentCanvas.planeDistance; canvasComp.sortingLayerName = parentCanvas.sortingLayerName; canvasComp.sortingOrder = parentCanvas.sortingOrder; } }); int canvasSize = Mathf.Min(value2, value - j * value2); PopulateCanvas(originalRect2, canvasSize, j, val); } SetupHUDLayout(); } private void PopulateCanvas(RectTransform originalRect, int canvasSize, int index, GameObject canvasObj) { RectTransform originalRect2 = originalRect; GameObject canvasObj2 = canvasObj; UsefulExtensions.Times(canvasSize, (Action)delegate { //IL_000d: 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) RectTransform val = Object.Instantiate<RectTransform>(originalRect2, ((Transform)originalRect2).position, ((Transform)originalRect2).rotation, canvasObj2.transform); 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; _freeNodes[index].Enqueue(new ScannedNode(val, header, val2, gameObject, index)); }); } private static void SetupHUDLayout() { GameObject val = GameObject.Find("Systems/UI/Canvas"); if ((Object)(object)val == (Object)null || !Object.op_Implicit((Object)(object)val)) { return; } Transform val2 = val.transform.Find("ObjectScanner"); if (!((Object)(object)val2 == (Object)null) && Object.op_Implicit((Object)(object)val2)) { val2.SetSiblingIndex(3); Transform val3 = val2.Find("GlobalScanInfo"); if ((Object)(object)val3 != (Object)null && Object.op_Implicit((Object)(object)val3)) { val3.SetAsLastSibling(); } } } public ScannedNode? DequeueNode() { foreach (Queue<ScannedNode> freeNode in _freeNodes) { if (!freeNode.TryDequeue(out var result)) { continue; } return result; } return null; } public void EnqueueNode(ScannedNode node) { if (node.canvasIndex < _freeNodes.Count) { _freeNodes[node.canvasIndex].Enqueue(node); } } public void ClearUpdateSets() { canvasesToUpdate.ForEach(delegate(HashSet<ScannedNode> set) { set.Clear(); }); } } public static class ScanValidator { private static readonly Vector3[] _CORNERS_BUFFER = (Vector3[])(object)new Vector3[8]; public static bool IsNodeVisible(ScanNodeProperties node, Vector3 viewPoint, bool forceCheckLos, ComponentCache componentCache) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: 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_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) if (!IsNodeOnScreen(viewPoint)) { return false; } if ((Object)(object)node == (Object)null || !Object.op_Implicit((Object)(object)node)) { return false; } PlayerControllerB localPlayerController = StartOfRound.Instance.localPlayerController; Vector3 position = ((Component)localPlayerController.gameplayCamera).transform.position; float num = CalculateDistance(viewPoint, ((Component)node).transform.position, position); int num2 = node.maxRange + ((node.nodeType == 1) ? CheatsAPI.additionalEnemyDistance : CheatsAPI.additionalDistance); if (num2 < node.maxRange) { num2 = int.MaxValue; } if (num > (float)num2 || num < (float)node.minRange) { return false; } if ((forceCheckLos || ConfigManager.alwaysCheckForLineOfSight.Value) && num > (float)CheatsAPI.noLineOfSightDistance && !HasLineOfSight(node, position)) { return false; } return IsScanNodeValid(node, componentCache); } public static bool IsNodeOnScreen(Vector3 viewPoint) { //IL_0001: 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_002f: Unknown result type (might be due to invalid IL or missing references) float x = viewPoint.x; int result; if (x >= 0f && x <= 1f) { x = viewPoint.y; if (x >= 0f && x <= 1f) { result = ((viewPoint.z > 0f) ? 1 : 0); goto IL_003f; } } result = 0; goto IL_003f; IL_003f: return (byte)result != 0; } public static float CalculateDistance(Vector3 viewPoint, Vector3 objectPosition, Vector3 cameraPosition) { //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) //IL_000d: Unknown result type (might be due to invalid IL or missing references) return ConfigManager.calculateDistance.Value ? Vector3.Distance(objectPosition, cameraPosition) : viewPoint.z; } public static bool HasLineOfSight(ScanNodeProperties node, Vector3 cameraPosition) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_005e: 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_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_008d: 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_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_00a6: 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_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: 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_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: 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_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0105: 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_0110: 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_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0133: 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 (!node.requiresLineOfSight) { return true; } if (!TryGetOrAddBoxCollider(node, out BoxCollider boxCollider)) { return false; } Bounds bounds = ((Collider)boxCollider).bounds; Vector3 min = ((Bounds)(ref bounds)).min; Vector3 max = ((Bounds)(ref bounds)).max; _CORNERS_BUFFER[0] = max; _CORNERS_BUFFER[1] = new Vector3(max.x, max.y, min.z); _CORNERS_BUFFER[2] = new Vector3(max.x, min.y, max.z); _CORNERS_BUFFER[3] = new Vector3(max.x, min.y, min.z); _CORNERS_BUFFER[4] = new Vector3(min.x, max.y, max.z); _CORNERS_BUFFER[5] = new Vector3(min.x, max.y, min.z); _CORNERS_BUFFER[6] = new Vector3(min.x, min.y, max.z); _CORNERS_BUFFER[7] = min; return _CORNERS_BUFFER.Any((Vector3 corner) => !Physics.Linecast(cameraPosition, corner, 256, (QueryTriggerInteraction)1)); } private static bool TryGetOrAddBoxCollider(ScanNodeProperties node, out BoxCollider boxCollider) { if (((Component)node).TryGetComponent<BoxCollider>(ref boxCollider)) { return true; } GoodItemScan.Logger.LogError((object)(node.headerText + " has no BoxCollider!")); if (!ConfigManager.addBoxCollidersToInvalidScanNodes.Value) { return false; } GoodItemScan.Logger.LogError((object)"Adding a BoxCollider!"); boxCollider = ((Component)node).gameObject.AddComponent<BoxCollider>(); return true; } public static bool IsScanNodeValid(ScanNodeProperties node, ComponentCache componentCache) { GameObject gameObject = ((Component)((Component)node).transform.parent).gameObject; if ((Object)(object)gameObject == (Object)null || !Object.op_Implicit((Object)(object)gameObject)) { return false; } (GrabbableObject, EnemyAI, TerminalAccessibleObject) components = componentCache.GetComponents(gameObject); return IsScanNodeValid(components.Item1, components.Item2, components.Item3); } public static bool IsScanNodeValid(GrabbableObject? grabbable, EnemyAI? enemy, TerminalAccessibleObject? terminal) { if ((Object)(object)grabbable != (Object)null && Object.op_Implicit((Object)(object)grabbable) && (grabbable.isHeld || grabbable.isHeldByEnemy || grabbable.deactivated)) { return false; } if ((Object)(object)enemy != (Object)null && Object.op_Implicit((Object)(object)enemy) && enemy.isEnemyDead) { return false; } if (ConfigManager.showOpenedBlastDoorScanNode.Value) { return true; } if ((Object)(object)terminal == (Object)null || !Object.op_Implicit((Object)(object)terminal) || !terminal.isBigDoor) { return true; } return terminal != null && !terminal.isDoorOpen && terminal.isPoweredOn; } } public class ScrapTracker { private int _scannedAmount; private int _scannedValue; private int _scannedValueDisplayed; private float _addToDisplayTotalInterval = 0.35f; public bool HasScrap => _scannedAmount > 0; public void Reset() { _scannedAmount = 0; _scannedValue = 0; _scannedValueDisplayed = 0; _addToDisplayTotalInterval = 0.35f; } public void AddScrap(ScanNodeProperties node) { if (node != null && node.nodeType == 2 && node.scrapValue > 0) { _scannedAmount++; _scannedValue += node.scrapValue; } } public void RemoveScrap(ScanNodeProperties node) { if (node != null && node.nodeType == 2 && node.scrapValue > 0) { _scannedAmount--; _scannedValue = Mathf.Clamp(_scannedValue - node.scrapValue, 0, 10000); } } public void UpdateDisplay(HUDManager hudManager, bool hasActiveNodes) { if (!hasActiveNodes || _scannedAmount <= 0) { ((TMP_Text)hudManager.totalValueText).text = "$0"; _scannedAmount = 0; _scannedValue = 0; _scannedValueDisplayed = 0; _addToDisplayTotalInterval = 0.35f; hudManager.scanInfoAnimator.SetBool(Scanner.DISPLAY_ANIMATOR_HASH, false); return; } hudManager.scanInfoAnimator.SetBool(Scanner.DISPLAY_ANIMATOR_HASH, _scannedValue != 0); if (_scannedValueDisplayed >= _scannedValue || _scannedValueDisplayed >= 10000) { return; } _addToDisplayTotalInterval -= Time.deltaTime; if (!(_addToDisplayTotalInterval > 0f)) { _addToDisplayTotalInterval = 0.08525f * ((float)ConfigManager.totalAddWaitMultiplier.Value / 100f); _scannedValueDisplayed = (int)Mathf.Clamp(Mathf.MoveTowards((float)_scannedValueDisplayed, (float)_scannedValue, (1500f + (float)(_scannedValue * ConfigManager.totalAddWaitMultiplier.Value) / 100f) * Time.deltaTime), 0f, 10000f); ((TMP_Text)hudManager.totalValueText).text = $"${_scannedValueDisplayed}"; if (_scannedValueDisplayed < _scannedValue && _scannedValueDisplayed < 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 = "2.0.3"; } } namespace GoodItemScan.Patches { [HarmonyPatch(typeof(HUDManager))] public static class HUDManagerPatch { [CompilerGenerated] private sealed class <>c__DisplayClass10_0 { public HUDManager hudManager; internal bool <PingScanRoutine>b__0() { return hudManager.CanPlayerScan() && (double)hudManager.playerPingingScan <= -1.0; } } [CompilerGenerated] private sealed class <PingScanRoutine>d__10 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; private <>c__DisplayClass10_0 <>8__1; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <PingScanRoutine>d__10(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>8__1 = null; <>1__state = -2; } private bool MoveNext() { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>8__1 = new <>c__DisplayClass10_0(); <>8__1.hudManager = HUDManager.Instance; break; case 1: <>1__state = -1; HUDManager.Instance.PingHUDElement(HUDManager.Instance.Compass, 1f, 0.8f, 0.12f); GoodItemScan.scanner?.Scan(); <>2__current = null; <>1__state = 2; return true; case 2: <>1__state = -1; break; } <>2__current = (object)new WaitUntil((Func<bool>)(() => <>8__1.hudManager.CanPlayerScan() && (double)<>8__1.hudManager.playerPingingScan <= -1.0)); <>1__state = 1; return true; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } 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; } HUDManager instance = HUDManager.Instance; if ((Object)(object)instance != (Object)null && Object.op_Implicit((Object)(object)instance)) { instance.PingHUDElement(instance.Compass, 1f, 0.8f, 0.12f); GoodItemScan.scanner?.Scan(); } return false; } [HarmonyPatch("Start")] [HarmonyPostfix] private static void AfterHudManagerAwake(HUDManager __instance) { GoodItemScan.scanner = new Scanner(); GoodItemScan.SetIncreasedMaximumScanNodes(__instance); RegisterHoldScan(); } private static void RegisterHoldScan() { Coroutine pingScanRoutine = null; InputAction val = InputSystem.actions.FindAction("PingScan", false); val.started += delegate { if (pingScanRoutine != null) { ((MonoBehaviour)HUDManager.Instance).StopCoroutine(pingScanRoutine); pingScanRoutine = null; } if (ConfigManager.holdToScan.Value) { pingScanRoutine = ((MonoBehaviour)HUDManager.Instance).StartCoroutine(PingScanRoutine()); } }; val.canceled += delegate { if (pingScanRoutine != null) { ((MonoBehaviour)HUDManager.Instance).StopCoroutine(pingScanRoutine); pingScanRoutine = null; } }; } [IteratorStateMachine(typeof(<PingScanRoutine>d__10))] private static IEnumerator PingScanRoutine() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <PingScanRoutine>d__10(0); } [HarmonyPatch("OnDisable")] [HarmonyPostfix] private static void ResetCheatsAPI() { CheatsAPI.additionalEnemyDistance = 0; CheatsAPI.additionalDistance = 0; CheatsAPI.noLineOfSightDistance = 0; } } [HarmonyPatch(typeof(Landmine))] public static class LandminePatch { [HarmonyPatch("Detonate")] [HarmonyPostfix] public static void DisableLandmineScanNode(Landmine __instance) { if (ConfigManager.fixLandmineScanNode.Value) { Transform val = ((Component)__instance).transform.parent.Find("ScanNode"); if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)((Component)val).gameObject)) { Object.Destroy((Object)(object)((Component)val).gameObject); } } } } [HarmonyPatch(typeof(StoryLog))] public class StoryLogPatch { [HarmonyPatch("RemoveLogCollectible")] [HarmonyPostfix] public static void DisableScanNode(StoryLog __instance) { BoxCollider[] componentsInChildren = ((Component)__instance).GetComponentsInChildren<BoxCollider>(); foreach (BoxCollider val in componentsInChildren) { Object.Destroy((Object)(object)((Component)val).gameObject); } } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }