Decompiled source of ElementalBounty v1.0.1

plugins/ElementalBounty.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;

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

[BepInPlugin("com.spencer4792.elementalbounty", "ElementalBounty", "1.0.0")]
public class ElementalBountyPlugin : BaseUnityPlugin
{
	public const string GUID = "com.spencer4792.elementalbounty";

	public const string NAME = "ElementalBounty";

	public const string VERSION = "1.0.0";

	internal static ManualLogSource Log;

	internal static ConfigEntry<string> NameMatch;

	internal static ConfigEntry<float> DropChanceMultiplier;

	internal static ConfigEntry<float> EmptyChanceDivisor;

	internal static ConfigEntry<bool> LogBoosts;

	internal static ConfigEntry<bool> GuaranteeDrops;

	internal static string[] Matchers = new string[0];

	private void Awake()
	{
		//IL_0129: Unknown result type (might be due to invalid IL or missing references)
		Log = ((BaseUnityPlugin)this).Logger;
		NameMatch = ((BaseUnityPlugin)this).Config.Bind<string>("General", "NameMatch", "Particle", "Comma-separated, case-insensitive substrings. Drop-table entries whose item name contains any of these get boosted. Default targets elemental particles.");
		DropChanceMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("General", "DropChanceMultiplier", 4f, "Multiplier applied to matching items' drop weight (1 = vanilla).");
		EmptyChanceDivisor = ((BaseUnityPlugin)this).Config.Bind<float>("General", "EmptyChanceDivisor", 2f, "Tables containing a matching item get their 'nothing drops' weight divided by this (1 = vanilla).");
		LogBoosts = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "LogBoosts", true, "Log each boosted drop entry (useful to verify what's being affected).");
		GuaranteeDrops = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "GuaranteeDrops", true, "Guarantee matching drops: tables containing a matching item lose their 'nothing drops' roll entirely and the matching item overwhelms other entries (~99.99%). Overrides DropChanceMultiplier for matched items.");
		string[] array = NameMatch.Value.Split(new char[1] { ',' });
		List<string> list = new List<string>();
		string[] array2 = array;
		foreach (string text in array2)
		{
			string text2 = text.Trim();
			if (text2.Length > 0)
			{
				list.Add(text2.ToLowerInvariant());
			}
		}
		Matchers = list.ToArray();
		new Harmony("com.spencer4792.elementalbounty").PatchAll();
		Log.LogMessage((object)("ElementalBounty 1.0.0 ready. Items matching [" + string.Join(", ", Matchers) + "]: " + ((!GuaranteeDrops.Value) ? ("x" + DropChanceMultiplier.Value + " weight, empty chance /" + EmptyChanceDivisor.Value) : "GUARANTEED drops") + ". Home key = drop-table dump."));
	}

	private void Update()
	{
		if (!InputHelper.GetKeyDown((KeyCode)278))
		{
			return;
		}
		try
		{
			DropTable[] array = Object.FindObjectsOfType(typeof(DropTable)) as DropTable[];
			Log.LogMessage((object)("=== Drop-table dump (v1.0.0): " + ((array != null) ? array.Length : 0) + " table(s) in scene ==="));
			if (array == null)
			{
				return;
			}
			FieldInfo field = typeof(DropTable).GetField("m_itemDrops", BindingFlags.Instance | BindingFlags.NonPublic);
			FieldInfo field2 = typeof(DropTable).GetField("m_emptyDropChance", BindingFlags.Instance | BindingFlags.NonPublic);
			DropTable[] array2 = array;
			foreach (DropTable val in array2)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				List<ItemDropChance> list = ((!(field != null)) ? null : (field.GetValue(val) as List<ItemDropChance>));
				int num = ((!(field2 != null)) ? (-1) : Convert.ToInt32(field2.GetValue(val)));
				Log.LogMessage((object)("TABLE '" + ((Object)((Component)val).gameObject).name + "' (root '" + ((Object)((Component)val).transform.root).name + "') entries=" + (list?.Count ?? 0) + " empty=" + num));
				if (list == null)
				{
					continue;
				}
				foreach (ItemDropChance item in list)
				{
					if (item != null)
					{
						Item droppedItem = ((BasicItemDrop)item).DroppedItem;
						Log.LogMessage((object)("    '" + ((!((Object)(object)droppedItem != (Object)null)) ? "(null)" : droppedItem.Name) + "' weight=" + item.DropChance + " count=" + ((BasicItemDrop)item).MinDropCount + "-" + ((BasicItemDrop)item).MaxDropCount));
					}
				}
			}
			Log.LogMessage((object)"=== end dump ===");
		}
		catch (Exception ex)
		{
			Log.LogError((object)("Drop dump: " + ex));
		}
	}

	internal static bool NameMatches(string itemName)
	{
		if (string.IsNullOrEmpty(itemName))
		{
			return false;
		}
		string text = itemName.ToLowerInvariant();
		string[] matchers = Matchers;
		foreach (string value in matchers)
		{
			if (text.Contains(value))
			{
				return true;
			}
		}
		return false;
	}
}
internal static class InputHelper
{
	private static readonly Type s_inputType = Type.GetType("UnityEngine.Input, UnityEngine.InputLegacyModule");

	private static readonly MethodInfo s_getKeyDown = ((!(s_inputType != null)) ? null : s_inputType.GetMethod("GetKeyDown", new Type[1] { typeof(KeyCode) }));

	public static bool GetKeyDown(KeyCode k)
	{
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		if (s_getKeyDown == null)
		{
			return false;
		}
		try
		{
			return (bool)s_getKeyDown.Invoke(null, new object[1] { k });
		}
		catch
		{
			return false;
		}
	}
}
[HarmonyPatch(typeof(DropTable), "CalculateChances")]
internal static class CalculateChancesPatch
{
	private static readonly HashSet<DropTable> s_boosted = new HashSet<DropTable>();

	private static readonly FieldInfo s_itemDropsField = typeof(DropTable).GetField("m_itemDrops", BindingFlags.Instance | BindingFlags.NonPublic);

	private static readonly FieldInfo s_emptyChanceField = typeof(DropTable).GetField("m_emptyDropChance", BindingFlags.Instance | BindingFlags.NonPublic);

	private static void Prefix(DropTable __instance)
	{
		try
		{
			if ((Object)(object)__instance == (Object)null || s_boosted.Contains(__instance))
			{
				return;
			}
			List<ItemDropChance> list = ((!(s_itemDropsField != null)) ? null : (s_itemDropsField.GetValue(__instance) as List<ItemDropChance>));
			if (list == null || list.Count == 0)
			{
				return;
			}
			bool flag = false;
			foreach (ItemDropChance item in list)
			{
				if (item == null)
				{
					continue;
				}
				Item droppedItem = ((BasicItemDrop)item).DroppedItem;
				if (!((Object)(object)droppedItem == (Object)null) && ElementalBountyPlugin.NameMatches(droppedItem.Name))
				{
					flag = true;
					int dropChance = item.DropChance;
					int num = (item.DropChance = ((!ElementalBountyPlugin.GuaranteeDrops.Value) ? Mathf.Max(1, Mathf.RoundToInt((float)dropChance * ElementalBountyPlugin.DropChanceMultiplier.Value)) : (Mathf.Max(1, dropChance) * 10000)));
					if (ElementalBountyPlugin.LogBoosts.Value)
					{
						ElementalBountyPlugin.Log.LogMessage((object)("Boosted '" + droppedItem.Name + "' weight " + dropChance + " -> " + num + " in table '" + ((Object)((Component)__instance).gameObject).name + "'."));
					}
				}
			}
			if (flag && s_emptyChanceField != null && (ElementalBountyPlugin.EmptyChanceDivisor.Value > 1f || ElementalBountyPlugin.GuaranteeDrops.Value))
			{
				int num2 = Convert.ToInt32(s_emptyChanceField.GetValue(__instance));
				if (num2 > 0)
				{
					int num3 = ((!ElementalBountyPlugin.GuaranteeDrops.Value) ? Mathf.Max(0, Mathf.RoundToInt((float)num2 / ElementalBountyPlugin.EmptyChanceDivisor.Value)) : 0);
					s_emptyChanceField.SetValue(__instance, num3);
					if (ElementalBountyPlugin.LogBoosts.Value)
					{
						ElementalBountyPlugin.Log.LogMessage((object)("Empty chance " + num2 + " -> " + num3 + " in table '" + ((Object)((Component)__instance).gameObject).name + "'."));
					}
				}
			}
			s_boosted.Add(__instance);
		}
		catch (Exception ex)
		{
			ElementalBountyPlugin.Log.LogWarning((object)("CalculateChances patch: " + ex.Message));
		}
	}
}