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