Decompiled source of Simple Smarter Corpse Run And Tombstone v1.0.1

SimpleSmarterCorpseRun.dll

Decompiled a year ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("SimpleSmarterCorpseRun")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("SimpleSmarterCorpseRun")]
[assembly: AssemblyCopyright("Copyright ©  2023")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("0c1ed8a1-1696-42a5-ac35-94bd79cde917")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.1.0")]
[module: UnverifiableCode]
namespace SimpleSmarterCorpseRun;

internal class CorpseRunMath
{
	private const int baseCarryingCapacity = 300;

	internal static bool HaveCustomCorpseRunEffect(Player player, out SE_Stats corpseRun)
	{
		SE_Stats val = null;
		foreach (StatusEffect statusEffect in ((Character)player).m_seman.m_statusEffects)
		{
			if (((Object)statusEffect).name == "GoldensCorpseRunWithCustomCarryWeight")
			{
				val = (SE_Stats)(object)((statusEffect is SE_Stats) ? statusEffect : null);
				break;
			}
		}
		corpseRun = val;
		return (Object)(object)corpseRun != (Object)null;
	}

	internal static void UpdateCustomCorpseRunEffect(Player player, SE_Stats oldCorpseRun)
	{
		float addMaxCarryWeight = CalculatePotentialExtraCarryingCapacity(((Humanoid)player).m_inventory.m_inventory, ((Humanoid)player).m_inventory.GetEquippedItems());
		oldCorpseRun.m_addMaxCarryWeight = addMaxCarryWeight;
	}

	internal static void AddCustomCorpseEffectRunToPlayer(Player player, SE_Stats oldCorpseRun)
	{
		float addMaxCarryWeight = CalculatePotentialExtraCarryingCapacity(((Humanoid)player).m_inventory.m_inventory, ((Humanoid)player).m_inventory.GetEquippedItems());
		StatusEffect obj = ((StatusEffect)oldCorpseRun).Clone();
		SE_Stats val = (SE_Stats)(object)((obj is SE_Stats) ? obj : null);
		((Object)val).name = "GoldensCorpseRunWithCustomCarryWeight";
		val.m_addMaxCarryWeight = addMaxCarryWeight;
		((Character)player).m_seman.AddStatusEffect((StatusEffect)(object)val, true, 0, 0f);
	}

	private static float GetCarryWeightBonus(ItemData item)
	{
		if (!CanHaveCarryWeightBonus(item))
		{
			return 0f;
		}
		float num = 300f;
		StatusEffect equipStatusEffect = item.m_shared.m_equipStatusEffect;
		if (equipStatusEffect != null)
		{
			equipStatusEffect.ModifyMaxCarryWeight(300f, ref num);
		}
		if (item.m_shared.m_setSize == 1)
		{
			StatusEffect setStatusEffect = item.m_shared.m_setStatusEffect;
			if (setStatusEffect != null)
			{
				setStatusEffect.ModifyMaxCarryWeight(300f, ref num);
			}
		}
		return num - 300f;
	}

	private static bool CanHaveCarryWeightBonus(ItemData item)
	{
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Invalid comparison between Unknown and I4
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Invalid comparison between Unknown and I4
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Invalid comparison between Unknown and I4
		return SimpleSmarterCorpseRunPlugin.WhichItemsToCheck.Value switch
		{
			ItemsToCheck.JustUtilityItems => item.IsEquipable() && (int)item.m_shared.m_itemType == 18, 
			ItemsToCheck.UtilityAndShoulderItems => (item.IsEquipable() && (int)item.m_shared.m_itemType == 18) || (int)item.m_shared.m_itemType == 17, 
			_ => item.IsEquipable(), 
		};
	}

	private static bool CanEquipMultipleUtilityItems()
	{
		return Chainloader.PluginInfos.ContainsKey("aedenthorn.EquipMultipleUtilityItems");
	}

	internal static float CalculatePotentialExtraCarryingCapacity(List<ItemData> inventory, List<ItemData> alreadyEquippedItems)
	{
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0113: Unknown result type (might be due to invalid IL or missing references)
		//IL_011a: Invalid comparison between Unknown and I4
		//IL_01be: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c5: Invalid comparison between Unknown and I4
		//IL_014e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0168: Unknown result type (might be due to invalid IL or missing references)
		//IL_0214: Unknown result type (might be due to invalid IL or missing references)
		bool flag = CanEquipMultipleUtilityItems();
		Dictionary<ItemType, float> dictionary = new Dictionary<ItemType, float>();
		foreach (ItemData alreadyEquippedItem in alreadyEquippedItems)
		{
			float carryWeightBonus = GetCarryWeightBonus(alreadyEquippedItem);
			if (!(carryWeightBonus <= 0f))
			{
				dictionary.TryGetValue(alreadyEquippedItem.m_shared.m_itemType, out var value);
				dictionary[alreadyEquippedItem.m_shared.m_itemType] = Math.Max(value, carryWeightBonus);
			}
		}
		Dictionary<string, float> dictionary2 = new Dictionary<string, float>();
		Dictionary<ItemType, float> dictionary3 = new Dictionary<ItemType, float>();
		foreach (ItemData invItem in inventory)
		{
			float carryWeightBonus2 = GetCarryWeightBonus(invItem);
			if (!(carryWeightBonus2 <= 0f) && (alreadyEquippedItems == null || !alreadyEquippedItems.Any((ItemData eItem) => eItem.m_shared.m_name == invItem.m_shared.m_name)))
			{
				if (flag && (int)invItem.m_shared.m_itemType == 18)
				{
					dictionary2[invItem.m_shared.m_name] = carryWeightBonus2;
				}
				dictionary3.TryGetValue(invItem.m_shared.m_itemType, out var value2);
				dictionary3[invItem.m_shared.m_itemType] = Math.Max(value2, carryWeightBonus2);
			}
		}
		float num = 0f;
		foreach (KeyValuePair<ItemType, float> item in dictionary3)
		{
			if (flag && (int)item.Key == 18)
			{
				foreach (KeyValuePair<string, float> item2 in dictionary2)
				{
					num += item2.Value;
				}
			}
			else
			{
				dictionary.TryGetValue(item.Key, out var value3);
				num += Math.Max(item.Value - value3, 0f);
			}
		}
		return num;
	}
}
internal class HumanoidPatches
{
	[HarmonyPatch(typeof(Humanoid), "EquipItem")]
	public static class Equip_Patch
	{
		private static void Prefix(Humanoid __instance, ItemData item, bool __result, ref float __state)
		{
			if (__result)
			{
				Player val = (Player)(object)((__instance is Player) ? __instance : null);
				if (val != null && !((Object)(object)val != (Object)(object)Player.m_localPlayer))
				{
					__state = val.GetMaxCarryWeight();
				}
			}
		}

		private static void Postfix(Humanoid __instance, ItemData item, bool __result, ref float __state)
		{
			if (__result)
			{
				Player val = (Player)(object)((__instance is Player) ? __instance : null);
				if (val != null && !((Object)(object)val != (Object)(object)Player.m_localPlayer) && __state != val.GetMaxCarryWeight() && CorpseRunMath.HaveCustomCorpseRunEffect(val, out var corpseRun))
				{
					CorpseRunMath.UpdateCustomCorpseRunEffect(val, corpseRun);
				}
			}
		}
	}
}
public enum ItemsToCheck
{
	JustUtilityItems,
	UtilityAndShoulderItems,
	AllEquippableItems
}
[BepInPlugin("goldenrevolver.SimpleSmarterCorpseRun", "Simple Smarter Corpse Run and Tombstone", "1.0.1")]
public class SimpleSmarterCorpseRunPlugin : BaseUnityPlugin
{
	public const string GUID = "goldenrevolver.SimpleSmarterCorpseRun";

	public const string NAME = "Simple Smarter Corpse Run and Tombstone";

	public const string VERSION = "1.0.1";

	public const string CustomCorpseRun = "GoldensCorpseRunWithCustomCarryWeight";

	public static ConfigEntry<bool> EnableSmartCorpseRunBuff;

	public static ConfigEntry<bool> EnableSmartTombStoneWeightCheck;

	public static ConfigEntry<bool> EnableSmartTombStoneSlotCheck;

	public static ConfigEntry<ItemsToCheck> WhichItemsToCheck;

	protected void Awake()
	{
		Helper.plugin = (BaseUnityPlugin)(object)this;
		LoadConfig();
		Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), (string)null);
	}

	private void LoadConfig()
	{
		string text = "General";
		EnableSmartCorpseRunBuff = ((BaseUnityPlugin)this).Config.Bind<bool>(text, "EnableSmartCorpseRunBuff", true, "Corpse Run now gives as much carrying capacity as reequipping your utility item would give and updates with every equipment change.");
		EnableSmartTombStoneWeightCheck = ((BaseUnityPlugin)this).Config.Bind<bool>(text, "EnableSmartTombStoneWeightCheck", true, "When trying to recover your tombstone, the tombstone now condiders the carrying capacity of reequipping your utility item from your tombstone.");
		EnableSmartTombStoneSlotCheck = ((BaseUnityPlugin)this).Config.Bind<bool>(text, "EnableSmartTombStoneSlotCheck", true, "When trying to recover your tombstone, the tombstone first tries to quick stack your inventory into the tombstone to free up more slots.");
		WhichItemsToCheck = ((BaseUnityPlugin)this).Config.Bind<ItemsToCheck>(text, "WhichItemsToCheck", ItemsToCheck.AllEquippableItems, "Only change if you have performance issues. Which items to check when calculating bonus carrying capacity. Megingjord is a utility items, Adventure backpacks and Jude's backpacks are shoulder items.");
	}
}
public class Helper
{
	internal static BaseUnityPlugin plugin;

	internal static void Log(object message, bool debug = true)
	{
		if (!debug)
		{
			Debug.LogWarning((object)("Simple Smarter Corpse Run and Tombstone 1.0.1: " + ((message != null) ? message.ToString() : "null")));
		}
	}
}
internal class TombStonePatches
{
	[HarmonyPatch(typeof(TombStone), "EasyFitInInventory")]
	public static class EasyFitInInventory_Patch
	{
		private static void Postfix(TombStone __instance, Player player, ref bool __result)
		{
			if (SimpleSmarterCorpseRunPlugin.EnableSmartTombStoneWeightCheck.Value && !(((Object)(object)player != (Object)(object)Player.m_localPlayer) | __result) && EasyFitInInventoryWithoutWeightCheck(__instance, player))
			{
				Inventory inventory = __instance.m_container.m_inventory;
				Inventory inventory2 = ((Humanoid)player).m_inventory;
				List<ItemData> list = new List<ItemData>();
				list.AddRange(inventory.m_inventory);
				list.AddRange(inventory2.m_inventory);
				float num = CorpseRunMath.CalculatePotentialExtraCarryingCapacity(list, inventory2.GetEquippedItems());
				if (inventory2.GetTotalWeight() + inventory.GetTotalWeight() <= player.GetMaxCarryWeight() + num)
				{
					__result = true;
				}
			}
		}
	}

	[HarmonyPatch(typeof(TombStone), "GiveBoost")]
	public static class GiveBoost_Patch
	{
		private static void Postfix(TombStone __instance)
		{
			if (!SimpleSmarterCorpseRunPlugin.EnableSmartCorpseRunBuff.Value)
			{
				return;
			}
			StatusEffect lootStatusEffect = __instance.m_lootStatusEffect;
			SE_Stats val = (SE_Stats)(object)((lootStatusEffect is SE_Stats) ? lootStatusEffect : null);
			if (val != null)
			{
				Player val2 = __instance.FindOwner();
				if (Object.op_Implicit((Object)(object)val2))
				{
					((Character)val2).m_seman.RemoveStatusEffect((StatusEffect)(object)val, true);
					CorpseRunMath.AddCustomCorpseEffectRunToPlayer(val2, val);
				}
			}
		}
	}

	private static bool EasyFitInInventoryWithoutWeightCheck(TombStone __instance, Player player)
	{
		int num = ((Humanoid)player).m_inventory.GetEmptySlots() - __instance.m_container.m_inventory.NrOfItems();
		if (num < 0)
		{
			foreach (ItemData allItem in __instance.m_container.m_inventory.GetAllItems())
			{
				if (((Humanoid)player).m_inventory.FindFreeStackSpace(allItem.m_shared.m_name, (float)allItem.m_worldLevel) >= allItem.m_stack)
				{
					num++;
				}
			}
			if (num < 0)
			{
				return false;
			}
		}
		return true;
	}
}
[HarmonyPatch(typeof(Inventory), "MoveAll")]
public static class Inventory_MoveAll_Patch
{
	[HarmonyPriority(500)]
	private static void Prefix(ref Inventory __instance, ref Inventory fromInventory)
	{
		if (!SimpleSmarterCorpseRunPlugin.EnableSmartTombStoneSlotCheck.Value || ((Humanoid)Player.m_localPlayer).m_inventory != __instance || !fromInventory.m_name.StartsWith("Grave"))
		{
			return;
		}
		List<ItemData> list = new List<ItemData>(__instance.GetAllItems());
		foreach (ItemData item in list)
		{
			if ((item.m_customData != null && item.m_customData.Count > 0) || item.m_shared.m_maxStackSize <= 1)
			{
				continue;
			}
			foreach (ItemData item2 in fromInventory.m_inventory)
			{
				if ((item2.m_customData == null || item2.m_customData.Count <= 0) && item2.m_shared.m_name == item.m_shared.m_name && item2.m_quality == item.m_quality)
				{
					int num = Math.Min(item2.m_shared.m_maxStackSize - item2.m_stack, item.m_stack);
					item2.m_stack += num;
					if (item.m_stack == num)
					{
						item.m_stack = 0;
						__instance.RemoveItem(item);
						break;
					}
					item.m_stack -= num;
				}
			}
		}
	}
}