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));
}
}
}