Decompiled source of LootVision v1.0.0

plugins/LootVision.dll

Decompiled 18 hours ago
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Fusion;
using HarmonyLib;
using HighlightPlus;
using UnityEngine;

[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace LordValdomodLootVision;

[BepInPlugin("LordValdomod.LootVision", "Loot Vision", "1.0.0")]
public class Plugin : BaseUnityPlugin
{
	internal static Plugin Inst;

	internal static ManualLogSource Log;

	internal ConfigEntry<bool> HighlightEnabled;

	internal ConfigEntry<float> Range;

	internal ConfigEntry<float> ViewAngle;

	internal ConfigEntry<float> OutlineWidth;

	internal ConfigEntry<float> Interval;

	internal ConfigEntry<string> OutlineColor;

	internal ConfigEntry<float> StockMultiplier;

	internal ConfigEntry<bool> ApplyOnLoad;

	private void Awake()
	{
		//IL_0136: Unknown result type (might be due to invalid IL or missing references)
		//IL_013c: Expected O, but got Unknown
		//IL_0156: Unknown result type (might be due to invalid IL or missing references)
		Inst = this;
		Log = ((BaseUnityPlugin)this).Logger;
		HighlightEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Highlight", "Enabled", true, "Outlines loot around you");
		Range = ((BaseUnityPlugin)this).Config.Bind<float>("Highlight", "Range", 10f, "Max distance in meters");
		ViewAngle = ((BaseUnityPlugin)this).Config.Bind<float>("Highlight", "ViewAngle", 60f, "Half angle of your view cone in degrees");
		OutlineColor = ((BaseUnityPlugin)this).Config.Bind<string>("Highlight", "Color", "#3CFF64", "Outline color in hex");
		OutlineWidth = ((BaseUnityPlugin)this).Config.Bind<float>("Highlight", "Width", 0.8f, "Outline width");
		Interval = ((BaseUnityPlugin)this).Config.Bind<float>("Highlight", "RefreshInterval", 0.2f, "Seconds between scans");
		StockMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Store", "StockMultiplier", 1.5f, "Multiplies the shop stock per run (host only)");
		ApplyOnLoad = ((BaseUnityPlugin)this).Config.Bind<bool>("Store", "ApplyOnLoad", true, "Also raises the stock already saved in the current run");
		GameObject val = new GameObject("LootVisionRunner");
		((Object)val).hideFlags = (HideFlags)61;
		Object.DontDestroyOnLoad((Object)(object)val);
		val.AddComponent<Runner>();
		new Harmony("LordValdomod.LootVision").PatchAll(typeof(StorePatches));
		Log.LogInfo((object)"Loot Vision loaded");
	}
}
public class Runner : MonoBehaviour
{
	private readonly Dictionary<Pickupable, HighlightEffect> active = new Dictionary<Pickupable, HighlightEffect>();

	private float timer;

	private Color color;

	private void Start()
	{
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		if (!ColorUtility.TryParseHtmlString(Plugin.Inst.OutlineColor.Value, ref color))
		{
			color = new Color(0.24f, 1f, 0.39f);
		}
	}

	private void Update()
	{
		timer -= Time.unscaledDeltaTime;
		if (timer > 0f)
		{
			return;
		}
		timer = Mathf.Max(0.05f, Plugin.Inst.Interval.Value);
		try
		{
			Scan();
		}
		catch (Exception ex)
		{
			Plugin.Log.LogError((object)("Highlight error: " + ex.Message));
		}
	}

	private void Scan()
	{
		//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_006a: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: 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_00e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f7: 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_00fd: 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_0123: 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_013c: Unknown result type (might be due to invalid IL or missing references)
		//IL_013d: 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)
		Camera main = Camera.main;
		if ((Object)(object)main == (Object)null || !Plugin.Inst.HighlightEnabled.Value)
		{
			ClearAll();
			return;
		}
		float value = Plugin.Inst.Range.Value;
		float num = Mathf.Cos(Plugin.Inst.ViewAngle.Value * ((float)Math.PI / 180f));
		Vector3 position = ((Component)main).transform.position;
		Vector3 forward = ((Component)main).transform.forward;
		HashSet<Pickupable> hashSet = new HashSet<Pickupable>();
		Collider[] array = Physics.OverlapSphere(position, value, -1, (QueryTriggerInteraction)1);
		RaycastHit val3 = default(RaycastHit);
		foreach (Collider val in array)
		{
			Pickupable componentInParent = ((Component)val).GetComponentInParent<Pickupable>();
			if ((Object)(object)componentInParent == (Object)null || (Object)(object)componentInParent.assignedItem == (Object)null || !componentInParent.assignedItem.isLoot || hashSet.Contains(componentInParent))
			{
				continue;
			}
			Bounds bounds = val.bounds;
			Vector3 center = ((Bounds)(ref bounds)).center;
			Vector3 val2 = center - position;
			float magnitude = ((Vector3)(ref val2)).magnitude;
			if (!(magnitude > value) && !(magnitude < 0.05f) && !(Vector3.Dot(forward, val2 / magnitude) < num) && (!Physics.Raycast(position, val2 / magnitude, ref val3, magnitude - 0.1f, -1, (QueryTriggerInteraction)1) || !((Object)(object)((Component)((RaycastHit)(ref val3)).collider).GetComponentInParent<Pickupable>() != (Object)(object)componentInParent)))
			{
				hashSet.Add(componentInParent);
				if (!active.ContainsKey(componentInParent))
				{
					active[componentInParent] = Attach(componentInParent);
				}
			}
		}
		foreach (Pickupable item in active.Keys.ToList())
		{
			if (!hashSet.Contains(item) || !((Object)(object)item != (Object)null))
			{
				HighlightEffect val4 = active[item];
				if ((Object)(object)val4 != (Object)null)
				{
					Object.Destroy((Object)(object)val4);
				}
				active.Remove(item);
			}
		}
	}

	private HighlightEffect Attach(Pickupable pk)
	{
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		HighlightEffect val = ((Component)pk).gameObject.AddComponent<HighlightEffect>();
		val.outline = 1f;
		val.outlineColor = color;
		val.outlineWidth = Plugin.Inst.OutlineWidth.Value;
		val.outlineVisibility = (Visibility)0;
		val.glow = 0f;
		val.overlay = 0f;
		val.SetHighlighted(true);
		return val;
	}

	private void ClearAll()
	{
		foreach (KeyValuePair<Pickupable, HighlightEffect> item in active)
		{
			if ((Object)(object)item.Value != (Object)null)
			{
				Object.Destroy((Object)(object)item.Value);
			}
		}
		active.Clear();
	}

	private void OnDestroy()
	{
		ClearAll();
	}
}
[HarmonyPatch]
internal static class StorePatches
{
	private static readonly HashSet<ShopButton> boosted = new HashSet<ShopButton>();

	private static readonly HashSet<ComputerStore> loaded = new HashSet<ComputerStore>();

	private static readonly FieldInfo ButtonsField = AccessTools.Field(typeof(ComputerStore), "shopButtons");

	private static float Mult => Mathf.Max(1f, Plugin.Inst.StockMultiplier.Value);

	private static List<ShopButton> Buttons(ComputerStore store)
	{
		return ButtonsField.GetValue(store) as List<ShopButton>;
	}

	[HarmonyPrefix]
	[HarmonyPatch(typeof(ComputerStore), "RestockItems")]
	private static void RestockPrefix(ComputerStore __instance)
	{
		try
		{
			List<ShopButton> list = Buttons(__instance);
			if (list == null)
			{
				return;
			}
			foreach (ShopButton item in list)
			{
				if (!((Object)(object)item == (Object)null) && !boosted.Contains(item))
				{
					item.stockMinRandom = Mathf.CeilToInt((float)item.stockMinRandom * Mult);
					item.stockMaxRandom = Mathf.CeilToInt((float)item.stockMaxRandom * Mult);
					boosted.Add(item);
				}
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogError((object)("Restock error: " + ex.Message));
		}
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(ComputerStore), "LoadAmountOfStock")]
	private static void LoadPostfix(ComputerStore __instance)
	{
		try
		{
			if (!Plugin.Inst.ApplyOnLoad.Value || loaded.Contains(__instance))
			{
				return;
			}
			List<ShopButton> list = Buttons(__instance);
			if (list == null)
			{
				return;
			}
			loaded.Add(__instance);
			foreach (ShopButton item in list)
			{
				if (!((Object)(object)item == (Object)null) && !((Object)(object)((SimulationBehaviour)item).Object == (Object)null) && ((SimulationBehaviour)item).Object.HasStateAuthority)
				{
					int amountInStock = item.amountInStock;
					if (amountInStock > 0)
					{
						item.amountInStock = Mathf.CeilToInt((float)amountInStock * Mult);
					}
				}
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogError((object)("Stock load error: " + ex.Message));
		}
	}
}