Decompiled source of Squeakys Item Multiplier v1.1.0

plugins/SqueakysItemMultiplier/SqueakyItemMultiplier.dll

Decompiled a month ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using On.RoR2;
using RoR2;
using UnityEngine;
using UnityEngine.Networking;

[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("SqueakyItemMultiplier")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyInformationalVersion("1.1.0+dc25b4ec0dda41b557d069171e5eb1cfc9500e6b")]
[assembly: AssemblyProduct("SqueakyItemMultiplier")]
[assembly: AssemblyTitle("SqueakyItemMultiplier")]
[assembly: AssemblyVersion("1.1.0.0")]
namespace SqueakyItemMultiplier;

internal sealed class GrantScaling
{
	private readonly ConditionalWeakTable<object, Dictionary<int, int>> _pickupCounts = new ConditionalWeakTable<object, Dictionary<int, int>>();

	public double GetFactor(object inventory, int itemIndex, int multiplier, bool exponential)
	{
		if (!exponential || multiplier <= 1)
		{
			return multiplier;
		}
		int value = 0;
		if (_pickupCounts.TryGetValue(inventory, out var value2))
		{
			value2.TryGetValue(itemIndex, out value);
		}
		return Math.Pow(multiplier, (double)value + 1.0);
	}

	public void RecordPickup(object inventory, int itemIndex)
	{
		Dictionary<int, int> orCreateValue = _pickupCounts.GetOrCreateValue(inventory);
		orCreateValue.TryGetValue(itemIndex, out var value);
		if (value < int.MaxValue)
		{
			orCreateValue[itemIndex] = value + 1;
		}
	}

	public void Reset()
	{
		_pickupCounts.Clear();
	}

	public static int ScalePermanent(int originalCount, int currentCount, double factor)
	{
		return (int)Math.Min((double)originalCount * factor, AvailableRoom(currentCount));
	}

	public static float ScaleTemporary(float originalCount, int currentCount, double factor)
	{
		double num = Math.Min((double)originalCount * factor, AvailableRoom(currentCount));
		float num2 = (float)num;
		if ((double)num2 > num)
		{
			num2 = BitConverter.Int32BitsToSingle(BitConverter.SingleToInt32Bits(num2) - 1);
		}
		return num2;
	}

	private static double AvailableRoom(int currentCount)
	{
		return Math.Min(2147483647L, Math.Max(0L, 2147483647L - (long)currentCount));
	}
}
[BepInPlugin("com.squeakysquared.squeakyitemmultiplier", "SqueakyItemMultiplier", "1.1.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class SqueakyItemMultiplierPlugin : BaseUnityPlugin
{
	private const string RiskOfOptionsGuid = "com.rune580.riskofoptions";

	private ConfigEntry<int> _itemMultiplier;

	private ConfigEntry<bool> _enableDebugLogging;

	private ConfigEntry<bool> _multiplyLunarItems;

	private ConfigEntry<bool> _multiplyVoidItems;

	private ConfigEntry<bool> _multiplyTemporaryItems;

	private ConfigEntry<bool> _exponentialItems;

	private readonly GrantScaling _grantScaling = new GrantScaling();

	private Inventory _activePickupInventory;

	private bool _scalingInventoryGrant;

	public void Awake()
	{
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_0041: Expected O, but got Unknown
		//IL_017b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0185: Expected O, but got Unknown
		//IL_018c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0196: Expected O, but got Unknown
		//IL_019d: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a7: Expected O, but got Unknown
		((BaseUnityPlugin)this).Logger.LogWarning((object)"=== SQUEAKY ITEM MULTIPLIER AWAKE START ===");
		_itemMultiplier = ((BaseUnityPlugin)this).Config.Bind<int>("Settings", "ItemMultiplier", 5, new ConfigDescription("Multiplier for items (e.g., 5 means 1 item becomes 5)", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, int.MaxValue), Array.Empty<object>()));
		_enableDebugLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "EnableDebugLogging", true, "Enable detailed logging");
		_multiplyLunarItems = ((BaseUnityPlugin)this).Config.Bind<bool>("Settings", "MultiplyLunarItems", true, "Multiply lunar (blue) items");
		_multiplyVoidItems = ((BaseUnityPlugin)this).Config.Bind<bool>("Settings", "MultiplyVoidItems", true, "Multiply void (purple) items");
		_multiplyTemporaryItems = ((BaseUnityPlugin)this).Config.Bind<bool>("Settings", "MultiplyTemporaryItems", false, "Multiply temporary items while keeping the additional stacks temporary");
		_exponentialItems = ((BaseUnityPlugin)this).Config.Bind<bool>("Settings", "ExponentialItems", false, "Grow grants per player and item type: at multiplier 5, successive pickups grant 5, 25, 125 copies. Only eligible pickups while this setting is enabled advance the sequence; resets each run.");
		RegisterRiskOfOptionsIfAvailable();
		((BaseUnityPlugin)this).Logger.LogWarning((object)($"=== CONFIG LOADED: Multiplier={_itemMultiplier.Value}, " + $"TemporaryItems={_multiplyTemporaryItems.Value}, Debug={_enableDebugLogging.Value} ==="));
		((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("{0} v{1} loaded! Multiplier: {2}x", "SqueakyItemMultiplier", "1.1.0", _itemMultiplier.Value));
		GenericPickupController.AttemptGrant += new hook_AttemptGrant(OnPickupAttemptGrant);
		Inventory.GiveItemPermanent_ItemIndex_int += new hook_GiveItemPermanent_ItemIndex_int(OnGiveItemPermanent);
		Inventory.GiveItemTemp += new hook_GiveItemTemp(OnGiveItemTemporary);
		Run.onRunStartGlobal += ResetPickupProgression;
		Run.onRunDestroyGlobal += ResetPickupProgression;
		((BaseUnityPlugin)this).Logger.LogWarning((object)"=== HOOK REGISTERED ===");
	}

	private void RegisterRiskOfOptionsIfAvailable()
	{
		if (!Chainloader.PluginInfos.ContainsKey("com.rune580.riskofoptions"))
		{
			return;
		}
		try
		{
			RegisterRiskOfOptions();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Registered settings with RiskOfOptions.");
		}
		catch (Exception arg)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)$"RiskOfOptions is installed, but its settings could not be registered: {arg}");
		}
	}

	[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
	private void RegisterRiskOfOptions()
	{
		Assembly assembly = ((object)Chainloader.PluginInfos["com.rune580.riskofoptions"].Instance).GetType().Assembly;
		Type type = assembly.GetType("RiskOfOptions.ModSettingsManager", throwOnError: true);
		Type type2 = assembly.GetType("RiskOfOptions.Options.BaseOption", throwOnError: true);
		Type type3 = assembly.GetType("RiskOfOptions.Options.IntFieldOption", throwOnError: true);
		Type type4 = assembly.GetType("RiskOfOptions.Options.CheckBoxOption", throwOnError: true);
		MethodInfo method = type.GetMethod("SetModDescription", new Type[3]
		{
			typeof(string),
			typeof(string),
			typeof(string)
		});
		MethodInfo method2 = type.GetMethod("AddOption", new Type[3]
		{
			type2,
			typeof(string),
			typeof(string)
		});
		if (method == null || method2 == null)
		{
			throw new MissingMethodException("The installed RiskOfOptions version does not expose the expected API.");
		}
		method.Invoke(null, new object[3] { "Configure how many copies of picked-up items are granted and which item types are affected.", "com.squeakysquared.squeakyitemmultiplier", "SqueakyItemMultiplier" });
		AddRiskOfOptionsEntry(method2, type3, (ConfigEntryBase)(object)_itemMultiplier);
		AddRiskOfOptionsEntry(method2, type4, (ConfigEntryBase)(object)_multiplyLunarItems);
		AddRiskOfOptionsEntry(method2, type4, (ConfigEntryBase)(object)_multiplyVoidItems);
		AddRiskOfOptionsEntry(method2, type4, (ConfigEntryBase)(object)_multiplyTemporaryItems);
		AddRiskOfOptionsEntry(method2, type4, (ConfigEntryBase)(object)_exponentialItems);
		AddRiskOfOptionsEntry(method2, type4, (ConfigEntryBase)(object)_enableDebugLogging);
	}

	private static void AddRiskOfOptionsEntry(MethodInfo addOption, Type optionType, ConfigEntryBase configEntry)
	{
		object obj = Activator.CreateInstance(optionType, configEntry);
		addOption.Invoke(null, new object[3] { obj, "com.squeakysquared.squeakyitemmultiplier", "SqueakyItemMultiplier" });
	}

	private void OnPickupAttemptGrant(orig_AttemptGrant orig, GenericPickupController self, CharacterBody body)
	{
		if ((Object)(object)body == (Object)null || (Object)(object)self == (Object)null || (Object)(object)body.inventory == (Object)null || _itemMultiplier.Value <= 1)
		{
			orig.Invoke(self, body);
			return;
		}
		if (!NetworkServer.active)
		{
			orig.Invoke(self, body);
			return;
		}
		Inventory activePickupInventory = _activePickupInventory;
		_activePickupInventory = body.inventory;
		try
		{
			orig.Invoke(self, body);
		}
		finally
		{
			_activePickupInventory = activePickupInventory;
		}
	}

	private void OnGiveItemPermanent(orig_GiveItemPermanent_ItemIndex_int orig, Inventory self, ItemIndex itemIndex, int count)
	{
		//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_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_007d: Expected I4, but got Unknown
		//IL_0088: 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_00d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d2: Expected I4, but got Unknown
		if (!ShouldScaleGrant(self, itemIndex, count > 0))
		{
			orig.Invoke(self, itemIndex, count);
			return;
		}
		bool value = _exponentialItems.Value;
		double factor = _grantScaling.GetFactor(self, (int)itemIndex, _itemMultiplier.Value, value);
		int scaledCount = GrantScaling.ScalePermanent(count, self.GetItemCountEffective(itemIndex), factor);
		GrantWithoutRescaling(delegate
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			orig.Invoke(self, itemIndex, scaledCount);
		});
		if (value && scaledCount > 0)
		{
			_grantScaling.RecordPickup(self, (int)itemIndex);
		}
		LogScaledGrant(itemIndex, count, scaledCount, isTemporary: false);
	}

	private void OnGiveItemTemporary(orig_GiveItemTemp orig, Inventory self, ItemIndex itemIndex, float countToAdd)
	{
		//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_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a0: Expected I4, but got Unknown
		//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fa: Expected I4, but got Unknown
		if (!_multiplyTemporaryItems.Value || !ShouldScaleGrant(self, itemIndex, countToAdd > 0f) || float.IsNaN(countToAdd) || float.IsInfinity(countToAdd))
		{
			orig.Invoke(self, itemIndex, countToAdd);
			return;
		}
		bool value = _exponentialItems.Value;
		double factor = _grantScaling.GetFactor(self, (int)itemIndex, _itemMultiplier.Value, value);
		float scaledCount = GrantScaling.ScaleTemporary(countToAdd, self.GetItemCountEffective(itemIndex), factor);
		if (!(scaledCount <= 0f))
		{
			GrantWithoutRescaling(delegate
			{
				//IL_000d: Unknown result type (might be due to invalid IL or missing references)
				orig.Invoke(self, itemIndex, scaledCount);
			});
			if (value)
			{
				_grantScaling.RecordPickup(self, (int)itemIndex);
			}
			LogScaledGrant(itemIndex, countToAdd, scaledCount, isTemporary: true);
		}
	}

	private bool ShouldScaleGrant(Inventory inventory, ItemIndex itemIndex, bool hasPositiveGrant)
	{
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		if (!hasPositiveGrant || _scalingInventoryGrant || (Object)(object)_activePickupInventory == (Object)null || (Object)(object)inventory != (Object)(object)_activePickupInventory || _itemMultiplier.Value <= 1)
		{
			return false;
		}
		return ShouldMultiplyItem(ItemCatalog.GetItemDef(itemIndex));
	}

	private void ResetPickupProgression(Run run)
	{
		_grantScaling.Reset();
	}

	private void GrantWithoutRescaling(Action grant)
	{
		bool scalingInventoryGrant = _scalingInventoryGrant;
		_scalingInventoryGrant = true;
		try
		{
			grant();
		}
		finally
		{
			_scalingInventoryGrant = scalingInventoryGrant;
		}
	}

	private unsafe void LogScaledGrant(ItemIndex itemIndex, object originalCount, object scaledCount, bool isTemporary)
	{
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		if (_enableDebugLogging.Value)
		{
			ItemDef itemDef = ItemCatalog.GetItemDef(itemIndex);
			string text = (isTemporary ? "temporary" : "permanent");
			string text2 = (((Object)(object)itemDef != (Object)null) ? itemDef.nameToken : ((object)(*(ItemIndex*)(&itemIndex))/*cast due to .constrained prefix*/).ToString());
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Multiplied " + text + " grant for " + text2 + ": " + $"{originalCount} -> {scaledCount}"));
		}
	}

	private bool ShouldMultiplyItem(ItemDef itemDef)
	{
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: Invalid comparison between Unknown and I4
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Invalid comparison between Unknown and I4
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Invalid comparison between Unknown and I4
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Invalid comparison between Unknown and I4
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Invalid comparison between Unknown and I4
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Invalid comparison between Unknown and I4
		if ((Object)(object)itemDef == (Object)null || (int)itemDef.tier == 5)
		{
			return false;
		}
		if ((int)itemDef.tier == 3 && !_multiplyLunarItems.Value)
		{
			return false;
		}
		if (((int)itemDef.tier == 6 || (int)itemDef.tier == 7 || (int)itemDef.tier == 8 || (int)itemDef.tier == 9) && !_multiplyVoidItems.Value)
		{
			return false;
		}
		if (!itemDef.ContainsTag((ItemTag)10))
		{
			return !itemDef.ContainsTag((ItemTag)9);
		}
		return false;
	}

	public void OnDestroy()
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Expected O, but got Unknown
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Expected O, but got Unknown
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Expected O, but got Unknown
		GenericPickupController.AttemptGrant -= new hook_AttemptGrant(OnPickupAttemptGrant);
		Inventory.GiveItemPermanent_ItemIndex_int -= new hook_GiveItemPermanent_ItemIndex_int(OnGiveItemPermanent);
		Inventory.GiveItemTemp -= new hook_GiveItemTemp(OnGiveItemTemporary);
		Run.onRunStartGlobal -= ResetPickupProgression;
		Run.onRunDestroyGlobal -= ResetPickupProgression;
		_grantScaling.Reset();
		((BaseUnityPlugin)this).Logger.LogInfo((object)"SqueakyItemMultiplier unloaded.");
	}
}
internal static class PluginInfo
{
	public const string PluginGuid = "com.squeakysquared.squeakyitemmultiplier";

	public const string PluginName = "SqueakyItemMultiplier";

	public const string PluginVersion = "1.1.0";
}