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 LootLens v4.0.3
BepInEx\plugins\LootLens.dll
Decompiled a day agousing System; 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.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using JetBrains.Annotations; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("LootLens")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("4.0.3.0")] [assembly: AssemblyInformationalVersion("4.0.3+5b855474c872e5e21e42242ff0a4237575a37199")] [assembly: AssemblyProduct("LootLens")] [assembly: AssemblyTitle("LootLens")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("4.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.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace LootLens { public static class ConfigManager { private const float MaxRadius = 100f; public static ConfigEntry<bool> scanValuables; public static ConfigEntry<bool> onlyDiscoveredValuables; public static ConfigEntry<bool> scanEnemies; public static ConfigEntry<bool> scanHeads; public static ConfigEntry<bool> scanItems; public static ConfigEntry<bool> scanCosmetics; public static ConfigEntry<bool> scanCartsVehicles; public static ConfigEntry<bool> scanCustom; public static ConfigEntry<float> scanRadius; public static ConfigEntry<bool> multiplayerReveal; public static ConfigEntry<float> radiusValuables; public static ConfigEntry<float> radiusEnemies; public static ConfigEntry<float> radiusHeads; public static ConfigEntry<float> radiusItems; public static ConfigEntry<float> radiusCosmetics; public static ConfigEntry<float> radiusCartsVehicles; public static ConfigEntry<float> radiusCustom; public static ConfigEntry<float> boxFillOpacity; private static bool _initialized; public static float MaxScanRadius { get { float value = scanRadius.Value; float num = 0f; if (scanValuables.Value) { num = Mathf.Max(num, (radiusValuables.Value > 0f) ? radiusValuables.Value : value); } if (scanEnemies.Value) { num = Mathf.Max(num, (radiusEnemies.Value > 0f) ? radiusEnemies.Value : value); } if (scanHeads.Value) { num = Mathf.Max(num, (radiusHeads.Value > 0f) ? radiusHeads.Value : value); } if (scanItems.Value) { num = Mathf.Max(num, (radiusItems.Value > 0f) ? radiusItems.Value : value); } if (scanCosmetics.Value) { num = Mathf.Max(num, (radiusCosmetics.Value > 0f) ? radiusCosmetics.Value : value); } if (scanCartsVehicles.Value) { num = Mathf.Max(num, (radiusCartsVehicles.Value > 0f) ? radiusCartsVehicles.Value : value); } if (scanCustom.Value) { num = Mathf.Max(num, (radiusCustom.Value > 0f) ? radiusCustom.Value : value); } return Mathf.Min(num, 100f); } } internal static void Initialize(Plugin plugin) { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown //IL_0224: Unknown result type (might be due to invalid IL or missing references) //IL_022e: Expected O, but got Unknown if (!_initialized) { _initialized = true; AcceptableValueRange<float> range = new AcceptableValueRange<float>(0f, 100f); AcceptableValueRange<float> val = new AcceptableValueRange<float>(2f, 100f); AcceptableValueRange<float> val2 = new AcceptableValueRange<float>(0f, 1f); scanRadius = ((BaseUnityPlugin)plugin).Config.Bind<float>("General", "Scan Radius", 10f, new ConfigDescription("Detection radius around the player (metres)", (AcceptableValueBase)(object)val, Array.Empty<object>())); multiplayerReveal = ((BaseUnityPlugin)plugin).Config.Bind<bool>("General", "Multiplayer Reveal", true, "Reveal scanned valuables on other players' minimaps via RPC"); scanValuables = ((BaseUnityPlugin)plugin).Config.Bind<bool>("Object Types", "Valuables", true, "Show boxes on valuable objects"); onlyDiscoveredValuables = ((BaseUnityPlugin)plugin).Config.Bind<bool>("Object Types", "Only Discovered Valuables", false, "Skip valuables that have not been discovered yet"); scanEnemies = ((BaseUnityPlugin)plugin).Config.Bind<bool>("Object Types", "Enemies", true, "Show boxes on enemies"); scanHeads = ((BaseUnityPlugin)plugin).Config.Bind<bool>("Object Types", "Player Heads", true, "Show boxes on dead player heads"); scanItems = ((BaseUnityPlugin)plugin).Config.Bind<bool>("Object Types", "Items", true, "Show boxes on equippable items"); scanCosmetics = ((BaseUnityPlugin)plugin).Config.Bind<bool>("Object Types", "Cosmetics", true, "Show boxes on cosmetic objects"); scanCartsVehicles = ((BaseUnityPlugin)plugin).Config.Bind<bool>("Object Types", "Carts and Vehicles", false, "Show boxes on carts and driveable vehicles (disabled by default to reduce clutter)"); scanCustom = ((BaseUnityPlugin)plugin).Config.Bind<bool>("Object Types", "Custom", true, "Show boxes on objects with a custom discover component"); scanRadiusDesc(plugin, "Valuables", out radiusValuables, range); scanRadiusDesc(plugin, "Enemies", out radiusEnemies, range); scanRadiusDesc(plugin, "Player Heads", out radiusHeads, range); scanRadiusDesc(plugin, "Items", out radiusItems, range); scanRadiusDesc(plugin, "Cosmetics", out radiusCosmetics, range); scanRadiusDesc(plugin, "Carts and Vehicles", out radiusCartsVehicles, range); scanRadiusDesc(plugin, "Custom", out radiusCustom, range); boxFillOpacity = ((BaseUnityPlugin)plugin).Config.Bind<float>("Display", "Box Fill Opacity", 0.15f, new ConfigDescription("Alpha of the box fill colour — 0 = invisible, 1 = solid (corners are unaffected)", (AcceptableValueBase)(object)val2, Array.Empty<object>())); } } private static void scanRadiusDesc(Plugin plugin, string key, out ConfigEntry<float> entry, AcceptableValueRange<float> range) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown entry = ((BaseUnityPlugin)plugin).Config.Bind<float>("Radius Overrides", key, 0f, new ConfigDescription("Detection radius override for " + key + " (0 = use global Scan Radius)", (AcceptableValueBase)(object)range, Array.Empty<object>())); } } [HarmonyPatch] public class Patches { private static FieldInfo _waitTimerField; private static FieldInfo _waitTimeField; private static FieldInfo _animLerpField; private static FieldInfo _middleField; private static readonly Dictionary<int, Image> _middleImageCache = new Dictionary<int, Image>(); [HarmonyPatch(typeof(PlayerController), "Update")] [HarmonyPostfix] private static void PlayerControllerUpdatePostfix() { Scanner.Update(); } [HarmonyPatch(typeof(ValuableDiscoverGraphic), "Update")] [HarmonyPostfix] private static void ValuableDiscoverGraphicUpdatePostfix(ValuableDiscoverGraphic __instance) { //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Expected O, but got Unknown //IL_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance.target == (Object)null) { return; } if ((object)_waitTimerField == null) { _waitTimerField = AccessTools.Field(typeof(ValuableDiscoverGraphic), "waitTimer"); } if ((object)_waitTimeField == null) { _waitTimeField = AccessTools.Field(typeof(ValuableDiscoverGraphic), "waitTime"); } if ((object)_animLerpField == null) { _animLerpField = AccessTools.Field(typeof(ValuableDiscoverGraphic), "animLerp"); } if ((object)_middleField == null) { _middleField = AccessTools.Field(typeof(ValuableDiscoverGraphic), "middle"); } if (_waitTimerField == null || _waitTimeField == null || _animLerpField == null) { return; } float num = (float)_waitTimerField.GetValue(__instance); if (Scanner.currentlyVisible.Contains(((Object)__instance.target).GetInstanceID())) { if (num <= 0f) { _waitTimerField.SetValue(__instance, (float)_waitTimeField.GetValue(__instance)); _animLerpField.SetValue(__instance, 1f); } } else if (num > 0f) { _waitTimerField.SetValue(__instance, 0f); } if (_middleField == null) { return; } int instanceID = ((Object)__instance).GetInstanceID(); if (!_middleImageCache.TryGetValue(instanceID, out var value) || (Object)(object)value == (Object)null) { RectTransform val = (RectTransform)_middleField.GetValue(__instance); value = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<Image>() : null); _middleImageCache[instanceID] = value; } if (!((Object)(object)value == (Object)null)) { float value2 = ConfigManager.boxFillOpacity.Value; Color color = ((Graphic)value).color; if (color.a != value2) { color.a = value2; ((Graphic)value).color = color; } } } } [BepInPlugin("LootLens", "LootLens", "4.0.3")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { internal static ManualLogSource Logger; private readonly Harmony harmony = new Harmony("LootLens"); internal static bool isCustomDiscoverStateLibLoaded; private void Awake() { Logger = ((BaseUnityPlugin)this).Logger; ConfigManager.Initialize(this); harmony.PatchAll(typeof(Patches)); Logger.LogInfo((object)$"Patched {harmony.GetPatchedMethods().Count()} methods!"); isCustomDiscoverStateLibLoaded = Chainloader.PluginInfos.ContainsKey("Kistras-CustomDiscoverStateLib"); if (!isCustomDiscoverStateLibLoaded) { Logger.LogInfo((object)"CustomDiscoverStateLib not loaded — falling back to Reminder graphic."); } Logger.LogInfo((object)"LootLens v4.0.3 loaded."); } } public class Scanner { private const State DiscoverValuableState = 0; private const State DiscoverEnemyState = 2; private static State discoverHeadState = NewCustomState(new Color(1f, 0f, 0.067f, 0.17f), new Color(1f, 0.1f, 0.067f, 0.75f)); private static State discoverItemState = NewCustomState(new Color(0f, 0.5f, 0.8f, 0.17f), new Color(0.1f, 0.6f, 0.9f, 0.75f)); private static State discoverCosmeticState = NewCustomState(new Color(0.1f, 0.8f, 0.5f, 0.17f), new Color(0.2f, 0.9f, 0.6f, 0.75f)); private static State discoverCartState = NewCustomState(new Color(0.8f, 0.6f, 0.1f, 0.17f), new Color(0.9f, 0.7f, 0.2f, 0.75f)); public static readonly HashSet<int> currentlyVisible = new HashSet<int>(); private static readonly HashSet<int> seenThisSweep = new HashSet<int>(); private const float SweepInterval = 0.25f; private static float lastSweepTime = 0f; private static bool isInitialized = false; private static State NewCustomState(Color middle, Color corner) { //IL_003c: 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_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_007a: Unknown result type (might be due to invalid IL or missing references) if (Plugin.isCustomDiscoverStateLibLoaded) { try { Type type = AccessTools.TypeByName("CustomDiscoverStateLib.CustomDiscoverState"); if (type != null) { MethodInfo methodInfo = AccessTools.Method(type, "AddNewDiscoverGraphic", (Type[])null, (Type[])null); if (methodInfo != null) { return (State)methodInfo.Invoke(null, new object[2] { middle, corner }); } } } catch (Exception ex) { Plugin.Logger.LogError((object)("CustomDiscoverState error: " + ex.Message)); } } return (State)1; } private static void Initialize() { if (!isInitialized) { isInitialized = true; Plugin.Logger.LogInfo((object)"LootLens scanner initialized"); } } [CanBeNull] private static T GetComponentOfType<T>(Collider col) where T : Component { return ((Component)col).GetComponentInParent<T>() ?? ((Component)col).GetComponentInChildren<T>(); } [CanBeNull] private static PhysGrabObject GetPhysGrab<TComponent>(TComponent component, Collider collider) where TComponent : MonoBehaviour { object obj = component; ValuableObject val = (ValuableObject)((obj is ValuableObject) ? obj : null); PhysGrabObject val5; if (val == null) { object obj2 = component; ItemAttributes val2 = (ItemAttributes)((obj2 is ItemAttributes) ? obj2 : null); if (val2 == null) { object obj3 = component; EnemyRigidbody val3 = (EnemyRigidbody)((obj3 is EnemyRigidbody) ? obj3 : null); if (val3 == null) { object obj4 = component; CosmeticWorldObject val4 = (CosmeticWorldObject)((obj4 is CosmeticWorldObject) ? obj4 : null); val5 = ((val4 != null) ? val4.physGrabObject : ((PhysGrabCart)(/*isinst with value type is only supported in some contexts*/?)).physGrabObject); } else { val5 = val3.physGrabObject; } } else { val5 = val2.physGrabObject; } } else { val5 = val.physGrabObject; } return val5 ?? ((Component)(object)component).GetComponentInParent<PhysGrabObject>() ?? ((Component)((Component)(object)component).transform.root).GetComponentInChildren<PhysGrabObject>(); } private static bool IsInFOV(Vector3 worldPos, Plane[] frustumPlanes) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) Bounds val = default(Bounds); ((Bounds)(ref val))..ctor(worldPos, Vector3.one * 0.5f); return GeometryUtility.TestPlanesAABB(frustumPlanes, val); } private static bool HasLineOfSight(Vector3 from, Vector3 to) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) Vector3 val = to - from; float magnitude = ((Vector3)(ref val)).magnitude; if (magnitude < 0.1f) { return true; } return !Physics.Raycast(from, val / magnitude, magnitude - 0.3f, -5, (QueryTriggerInteraction)1); } public static void Update() { //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: 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_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_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Unknown result type (might be due to invalid IL or missing references) //IL_023b: Unknown result type (might be due to invalid IL or missing references) //IL_023d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)LevelGenerator.Instance == (Object)null || !LevelGenerator.Instance.Generated || SemiFunc.MenuLevel()) { return; } if (!isInitialized) { Initialize(); } if (Time.time - lastSweepTime < 0.25f) { return; } lastSweepTime = Time.time; Camera main = Camera.main; if ((Object)(object)main == (Object)null || (Object)(object)PlayerController.instance == (Object)null) { return; } Vector3 position = ((Component)main).transform.position; Plane[] frustumPlanes = GeometryUtility.CalculateFrustumPlanes(main); Collider[] array = Physics.OverlapSphere(position, ConfigManager.MaxScanRadius); seenThisSweep.Clear(); Collider[] array2 = array; foreach (Collider val in array2) { if ((Object)(object)val == (Object)null || (Object)(object)((Component)val).transform == (Object)null) { continue; } Vector3 position2 = ((Component)val).transform.position; if (!IsInFOV(position2, frustumPlanes) || !HasLineOfSight(position, position2)) { continue; } PhysGrabObjectImpactDetector componentOfType = GetComponentOfType<PhysGrabObjectImpactDetector>(val); if (((Object)(object)componentOfType != (Object)null && componentOfType.inCart) || (!ConfigManager.scanCartsVehicles.Value && ((Object)(object)GetComponentOfType<PhysGrabCart>(val) != (Object)null || (Object)(object)GetComponentOfType<ItemVehicle>(val) != (Object)null)) || TryScanItem<ValuableObject>(val, ConfigManager.scanValuables, position, ConfigManager.radiusValuables, (State)0) || TryScanItem<EnemyRigidbody>(val, ConfigManager.scanEnemies, position, ConfigManager.radiusEnemies, (State)2) || TryScanItem<PlayerDeathHead>(val, ConfigManager.scanHeads, position, ConfigManager.radiusHeads, discoverHeadState) || TryScanItem<ItemAttributes>(val, ConfigManager.scanItems, position, ConfigManager.radiusItems, discoverItemState) || TryScanItem<CosmeticWorldObject>(val, ConfigManager.scanCosmetics, position, ConfigManager.radiusCosmetics, discoverCosmeticState) || TryScanItem<PhysGrabCart>(val, ConfigManager.scanCartsVehicles, position, ConfigManager.radiusCartsVehicles, discoverCartState) || TryScanItem<ItemVehicle>(val, ConfigManager.scanCartsVehicles, position, ConfigManager.radiusCartsVehicles, discoverCartState)) { continue; } ValuableDiscoverCustom componentOfType2 = GetComponentOfType<ValuableDiscoverCustom>(val); if (!((Object)(object)componentOfType2 != (Object)null) || !ConfigManager.scanCustom.Value) { continue; } float num = ((ConfigManager.radiusCustom.Value > 0f) ? ConfigManager.radiusCustom.Value : ConfigManager.scanRadius.Value); if (!(Vector3.Distance(position2, position) <= num)) { continue; } PhysGrabObject componentOfType3 = GetComponentOfType<PhysGrabObject>(val); if ((Object)(object)componentOfType3 != (Object)null) { int instanceID = ((Object)componentOfType3).GetInstanceID(); seenThisSweep.Add(instanceID); if (!currentlyVisible.Contains(instanceID)) { ValuableDiscover.instance.New(componentOfType3, (State)3, componentOfType2); } } } currentlyVisible.RemoveWhere((int id) => !seenThisSweep.Contains(id)); foreach (int item in seenThisSweep) { currentlyVisible.Add(item); } } private static bool TryScanItem<TComponent>(Collider collider, ConfigEntry<bool> shouldScan, Vector3 camPos, ConfigEntry<float> radiusOverride, State state) where TComponent : MonoBehaviour { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: 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) if (!shouldScan.Value) { return false; } TComponent componentOfType = GetComponentOfType<TComponent>(collider); if ((Object)(object)componentOfType == (Object)null) { return false; } float num = ((radiusOverride.Value > 0f) ? radiusOverride.Value : ConfigManager.scanRadius.Value); if (Vector3.Distance(((Component)(object)componentOfType).transform.position, camPos) > num) { return false; } if (ConfigManager.onlyDiscoveredValuables.Value) { object obj = componentOfType; ValuableObject val = (ValuableObject)((obj is ValuableObject) ? obj : null); if (val != null && !val.discovered) { return false; } } PhysGrabObject physGrab = GetPhysGrab(componentOfType, collider); if ((Object)(object)physGrab == (Object)null) { return true; } int instanceID = ((Object)physGrab).GetInstanceID(); seenThisSweep.Add(instanceID); if (currentlyVisible.Contains(instanceID)) { return true; } if (ConfigManager.multiplayerReveal.Value) { object obj2 = componentOfType; ValuableObject val2 = (ValuableObject)((obj2 is ValuableObject) ? obj2 : null); if (val2 != null && !val2.discovered) { val2.Discover(state); goto IL_00fe; } } ValuableDiscover.instance.New(physGrab, state, GetComponentOfType<ValuableDiscoverCustom>(collider)); goto IL_00fe; IL_00fe: return true; } public static bool IsOnCooldown() { return false; } public static float GetRemainingCooldown() { return 0f; } } public static class MyPluginInfo { public const string PLUGIN_GUID = "LootLens"; public const string PLUGIN_NAME = "LootLens"; public const string PLUGIN_VERSION = "4.0.3"; } }