Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of InventorySlotUpgrade v0.1.9
InventorySlotUpgrade.dll
Decompiled a month agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using REPOLib.Modules; using Steamworks; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; [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("InventorySlotUpgrade")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.1.9.0")] [assembly: AssemblyInformationalVersion("0.1.9+0550e1161febd14822a2240968cabacf4c176ee0")] [assembly: AssemblyProduct("InventorySlotUpgrade")] [assembly: AssemblyTitle("InventorySlotUpgrade")] [assembly: AssemblyVersion("0.1.9.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace InventorySlotUpgrade { [HarmonyPatch] internal static class ExtraSlotPersistence { private static readonly Dictionary<string, Dictionary<int, int>> EquippedItems = new Dictionary<string, Dictionary<int, int>>(); [HarmonyPostfix] [HarmonyPatch(typeof(StatsManager), "PlayerInventoryUpdate")] private static void TrackExtraSlot(string _steamID, string itemName, int spot) { if (!SemiFunc.IsMasterClientOrSingleplayer() || spot < 3) { return; } if (string.IsNullOrEmpty(itemName)) { Erase(_steamID, spot); } else if (spot < InventorySlotController.GetSlotCount(_steamID)) { if (!EquippedItems.TryGetValue(_steamID, out var value)) { value = new Dictionary<int, int>(); EquippedItems[_steamID] = value; } value[spot] = itemName.GetHashCode(); } } [HarmonyPostfix] [HarmonyPatch(typeof(PunManager), "SetItemNameLOGIC", new Type[] { typeof(string), typeof(int), typeof(ItemAttributes) })] private static void RestoreExtraSlot(string _name, int photonViewID, ItemAttributes _itemAttributes) { if (!SemiFunc.IsMasterClientOrSingleplayer()) { return; } ItemAttributes val = _itemAttributes; if ((Object)(object)val == (Object)null && SemiFunc.IsMultiplayer()) { PhotonView obj = PhotonView.Find(photonViewID); val = ((obj != null) ? ((Component)obj).GetComponent<ItemAttributes>() : null); } ItemEquippable val2 = ((val != null) ? ((Component)val).GetComponent<ItemEquippable>() : null); if ((Object)(object)val2 == (Object)null) { return; } int nameHash = _name.GetHashCode(); foreach (PlayerAvatar item in SemiFunc.PlayerGetList()) { string text = SemiFunc.PlayerGetSteamID(item); if (!EquippedItems.TryGetValue(text, out var value)) { continue; } KeyValuePair<int, int>? keyValuePair = value.FirstOrDefault((KeyValuePair<int, int> pair) => pair.Value == nameHash); if (keyValuePair.HasValue && keyValuePair.Value.Value == nameHash) { int key = keyValuePair.Value.Key; if (key >= InventorySlotController.GetSlotCount(text)) { Erase(text, key); break; } int num = (SemiFunc.IsMultiplayer() ? item.photonView.ViewID : (-1)); val2.RequestEquip(key, num); Erase(text, key); break; } } } [HarmonyPostfix] [HarmonyPatch(typeof(MainMenuOpen), "Start")] private static void ClearOnMainMenu() { EquippedItems.Clear(); } private static void Erase(string steamId, int slot) { if (EquippedItems.TryGetValue(steamId, out var value)) { value.Remove(slot); if (value.Count == 0) { EquippedItems.Remove(steamId); } } } } [HarmonyPatch] internal static class InventoryPatches { private static readonly FieldInfo InputDisableTimerField = AccessTools.Field(typeof(PlayerController), "InputDisableTimer"); private static readonly FieldInfo GrabbedPhysObjectField = AccessTools.Field(typeof(PhysGrabber), "grabbedPhysGrabObject"); [HarmonyPostfix] [HarmonyPatch(typeof(Inventory), "Awake")] private static void InventoryAwakePostfix(Inventory __instance) { InventorySlotController.ExpandInternalListEarly(__instance); } [HarmonyPostfix] [HarmonyPatch(typeof(InventoryUI), "Start")] private static void InventoryUiStartPostfix() { InventorySlotController.RequestRefresh(); } [HarmonyPrefix] [HarmonyPatch(typeof(InventorySpot), "Start")] private static void InventorySpotStartPrefix(InventorySpot __instance) { if (__instance.inventorySpotIndex >= 3) { BatteryVisualLogic componentInChildren = ((Component)__instance).GetComponentInChildren<BatteryVisualLogic>(true); if ((Object)(object)componentInChildren != (Object)null) { ((Component)componentInChildren).gameObject.SetActive(true); } else { Plugin.Log.LogError((object)$"Inventory slot {__instance.inventorySpotIndex + 1} has no BatteryVisualLogic child."); } } } [HarmonyPrefix] [HarmonyPatch(typeof(InventorySpot), "Update")] private static void InventorySpotUpdatePrefix(InventorySpot __instance) { int inventorySpotIndex = __instance.inventorySpotIndex; if (inventorySpotIndex < 3 || inventorySpotIndex >= InventorySlotController.GetLocalSlotCount()) { return; } Keyboard current = Keyboard.current; if (current == null) { return; } KeyControl val = (KeyControl)(inventorySpotIndex switch { 3 => current.digit4Key, 4 => current.digit5Key, 5 => current.digit6Key, 6 => current.digit7Key, 7 => current.digit8Key, 8 => current.digit9Key, 9 => current.digit0Key, _ => null, }); if (val == null || !((ButtonControl)val).wasPressedThisFrame || SemiFunc.RunIsArena() || (Object)(object)PlayerController.instance == (Object)null || IsPlayerInputDisabled()) { return; } if (__instance.IsOccupied()) { ItemEquippable currentItem = __instance.CurrentItem; if (currentItem != null) { currentItem.RequestUnequip(); } return; } PhysGrabber instance = PhysGrabber.instance; object obj; if (!((Object)(object)instance != (Object)null) || !instance.grabbed) { obj = null; } else { object? obj2 = GrabbedPhysObjectField?.GetValue(instance); object? obj3 = ((obj2 is PhysGrabObject) ? obj2 : null); obj = ((obj3 != null) ? ((Component)obj3).GetComponent<ItemEquippable>() : null); } ItemEquippable val2 = (ItemEquippable)obj; if ((Object)(object)val2 != (Object)null) { int num = (((Object)(object)instance.photonView != (Object)null) ? instance.photonView.ViewID : (-1)); val2.RequestEquip(inventorySpotIndex, num); } } private static bool IsPlayerInputDisabled() { if (InputDisableTimerField?.GetValue(PlayerController.instance) is float num) { return num > 0f; } return false; } [HarmonyPrefix] [HarmonyPatch(typeof(Inventory), "GetFirstFreeInventorySpotIndex")] private static bool FirstFreeSpotPrefix(Inventory __instance, ref int __result) { List<InventorySpot> spots = InventorySlotController.GetSpots(__instance); int num = Math.Min(InventorySlotController.GetLocalSlotCount(), spots?.Count ?? 0); for (int i = 0; i < num; i++) { InventorySpot val = spots[i]; if ((Object)(object)val != (Object)null && !val.IsOccupied()) { __result = i; return false; } } __result = -1; return false; } [HarmonyPrefix] [HarmonyPatch(typeof(ItemEquippable), "RPC_RequestEquip")] private static bool ValidateRequestedSlot(int spotIndex, int physGrabberPhotonViewID) { if (spotIndex < 3) { return true; } int num; string arg; if (!SemiFunc.IsMultiplayer()) { num = InventorySlotController.GetLocalSlotCount(); arg = "local player"; } else { PhotonView val = PhotonView.Find(physGrabberPhotonViewID); PlayerAvatar val2 = ((val != null) ? ((Component)val).GetComponent<PlayerAvatar>() : null) ?? ((val != null) ? ((Component)val).GetComponentInParent<PlayerAvatar>() : null); if ((Object)(object)val2 == (Object)null) { Plugin.Log.LogWarning((object)$"Rejected inventory slot {spotIndex + 1}: requesting player could not be resolved."); return false; } num = InventorySlotController.GetSlotCount(val2); arg = SemiFunc.PlayerGetName(val2); } bool num2 = spotIndex < num; if (!num2) { Plugin.Log.LogWarning((object)$"Rejected inventory slot {spotIndex + 1} for {arg}; allowed slot count is {num}."); } return num2; } } internal static class InventorySlotController { private const float SlotSpacing = 40f; private static readonly FieldInfo InventorySpotsField = AccessTools.Field(typeof(Inventory), "inventorySpots"); private static readonly FieldInfo UiChildrenField = AccessTools.Field(typeof(InventoryUI), "allChildren"); private static readonly FieldInfo InitialPositionField = AccessTools.Field(typeof(SemiUI), "initialPosition"); private static readonly FieldInfo HidePositionCurrentField = AccessTools.Field(typeof(SemiUI), "hidePositionCurrent"); private static readonly FieldInfo HideTimerField = AccessTools.Field(typeof(SemiUI), "hideTimer"); private static readonly FieldInfo ShowTimerField = AccessTools.Field(typeof(SemiUI), "showTimer"); private static readonly FieldInfo PreviousHideTimerField = AccessTools.Field(typeof(SemiUI), "prevHideTimer"); private static readonly FieldInfo PreviousShowTimerField = AccessTools.Field(typeof(SemiUI), "prevShowTimer"); private static readonly FieldInfo ScootPositionField = AccessTools.Field(typeof(SemiUI), "scootPosition"); private static readonly FieldInfo ScootPositionStartField = AccessTools.Field(typeof(SemiUI), "scootPositionStart"); private static readonly FieldInfo ScootPositionPreviousField = AccessTools.Field(typeof(SemiUI), "scootPositionPrev"); private static readonly FieldInfo ScootPositionCurrentField = AccessTools.Field(typeof(SemiUI), "scootPositionCurrent"); private static readonly FieldInfo ScootTimerField = AccessTools.Field(typeof(SemiUI), "scootTimer"); private static readonly FieldInfo PreviousScootTimerField = AccessTools.Field(typeof(SemiUI), "prevScootTimer"); private static readonly FieldInfo ScootAnimationEvaluationField = AccessTools.Field(typeof(SemiUI), "scootAnimationEvaluation"); private static readonly FieldInfo ScootEvaluationField = AccessTools.Field(typeof(SemiUI), "scootEval"); private static int _localLevelHint; private static int _refreshGeneration; internal static int GetSlotCount(string steamId) { int num = ((!string.IsNullOrEmpty(steamId) && Plugin.SlotUpgrade != null) ? Plugin.SlotUpgrade.GetLevel(steamId) : 0); return Mathf.Clamp(3 + num, 3, Plugin.EffectiveMaximumSlots); } internal static int GetSlotCount(PlayerAvatar playerAvatar) { if (!((Object)(object)playerAvatar == (Object)null)) { return GetSlotCount(SemiFunc.PlayerGetSteamID(playerAvatar)); } return 3; } internal static int GetLocalSlotCount() { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) PlayerAvatar val = PlayerController.instance?.playerAvatarScript; if ((Object)(object)val != (Object)null) { return GetSlotCount(val); } try { if (SteamClient.IsValid) { return GetSlotCount(((object)SteamClient.SteamId/*cast due to .constrained prefix*/).ToString()); } } catch { } return Mathf.Clamp(3 + _localLevelHint, 3, Plugin.EffectiveMaximumSlots); } internal static void ApplyUpgradeLevel(PlayerAvatar playerAvatar, int level) { if (!((Object)(object)playerAvatar == (Object)null) && !((Object)(object)playerAvatar != (Object)(object)PlayerController.instance?.playerAvatarScript)) { _localLevelHint = level; RequestRefresh(); Plugin.Log.LogInfo((object)$"Applied Inventory Slot level {level}; local inventory target is {GetSlotCount(playerAvatar)} slots."); } } internal static void RequestRefresh() { if (!((Object)(object)Plugin.Instance == (Object)null)) { int generation = ++_refreshGeneration; ((MonoBehaviour)Plugin.Instance).StartCoroutine(RefreshWhenReady(generation)); } } internal static void ExpandInternalListEarly(Inventory inventory) { List<InventorySpot> spots = GetSpots(inventory); if (spots != null) { int localSlotCount = GetLocalSlotCount(); while (spots.Count < localSlotCount) { spots.Add(null); } } } internal static List<InventorySpot> GetSpots(Inventory inventory) { if (!((Object)(object)inventory == (Object)null)) { return InventorySpotsField.GetValue(inventory) as List<InventorySpot>; } return null; } private static IEnumerator RefreshWhenReady(int generation) { while (generation == _refreshGeneration && ((Object)(object)Inventory.instance == (Object)null || (Object)(object)InventoryUI.instance == (Object)null)) { yield return null; } if (generation != _refreshGeneration) { yield break; } yield return null; if (generation != _refreshGeneration) { yield break; } int targetCount = GetLocalSlotCount(); List<InventorySpot> newlyClonedSlots = ApplyVisuals(targetCount); yield return null; if (generation != _refreshGeneration) { yield break; } ApplyVisuals(targetCount); foreach (InventorySpot item in newlyClonedSlots) { ForceSlotShown(item); } } private static List<InventorySpot> ApplyVisuals(int targetCount) { List<InventorySpot> list = new List<InventorySpot>(); Inventory instance = Inventory.instance; InventoryUI instance2 = InventoryUI.instance; List<InventorySpot> spots = GetSpots(instance); if ((Object)(object)instance == (Object)null || (Object)(object)instance2 == (Object)null || spots == null) { return list; } Transform transform = ((Component)instance2).transform; Transform val = transform.Find("Inventory Spot 1"); if ((Object)(object)val == (Object)null) { Plugin.Log.LogError((object)"Could not find the vanilla 'Inventory Spot 1' UI template."); return list; } List<GameObject> list2 = UiChildrenField.GetValue(instance2) as List<GameObject>; HashSet<InventorySpot> hashSet = new HashSet<InventorySpot>(); float num = (0f - (float)targetCount * 40f) / 2f + 20f; for (int i = 3; i < targetCount; i++) { Transform val2 = transform.Find($"Inventory Spot {i + 1}"); bool flag = (Object)(object)val2 == (Object)null; if ((Object)(object)val2 == (Object)null) { val2 = Object.Instantiate<Transform>(val, val.parent); ((Object)val2).name = $"Inventory Spot {i + 1}"; } InventorySpot component = ((Component)val2).GetComponent<InventorySpot>(); if ((Object)(object)component == (Object)null) { Plugin.Log.LogError((object)$"Cloned inventory slot {i + 1} has no InventorySpot component."); continue; } component.inventorySpotIndex = i; if (flag) { PrepareCloneForStart(((Component)val).GetComponent<InventorySpot>(), component, num + (float)i * 40f); hashSet.Add(component); list.Add(component); } SetKeyLabel(val2, component, i); ((Component)val2).gameObject.SetActive(true); while (spots.Count <= i) { spots.Add(null); } spots[i] = component; if (list2 != null && !list2.Contains(((Component)val2).gameObject)) { list2.Add(((Component)val2).gameObject); } } for (int j = 0; j < targetCount; j++) { Transform val3 = transform.Find($"Inventory Spot {j + 1}"); if (!((Object)(object)val3 == (Object)null)) { InventorySpot component2 = ((Component)val3).GetComponent<InventorySpot>(); if (!hashSet.Contains(component2)) { PositionStartedSlot(component2, num + (float)j * 40f); } } } return list; } private static void PrepareCloneForStart(InventorySpot template, InventorySpot clone, float desiredX) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: 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_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) Vector3 localPosition = ((Component)clone).transform.localPosition; float num = (((Object)(object)template == (Object)null || !((SemiUI)clone).animateTheEntireObject) ? localPosition.y : ((SemiUI)template).showPosition.y); ((Component)clone).transform.localPosition = new Vector3(desiredX, num, localPosition.z); if (!((SemiUI)clone).animateTheEntireObject && (Object)(object)((SemiUI)clone).textRectTransform != (Object)null && (Object)(object)template != (Object)null) { Vector3 localPosition2 = ((SemiUI)clone).textRectTransform.localPosition; ((SemiUI)clone).textRectTransform.localPosition = new Vector3(((SemiUI)template).showPosition.x, ((SemiUI)template).showPosition.y, localPosition2.z); } Vector2 val = (((Object)(object)template == (Object)null) ? Vector2.zero : (((SemiUI)template).hidePosition - ((SemiUI)template).showPosition)); ((SemiUI)clone).showPosition = Vector2.zero; ((SemiUI)clone).hidePosition = val; InitialPositionField?.SetValue(clone, ((Component)clone).transform.localPosition); HidePositionCurrentField?.SetValue(clone, val); ScootPositionField?.SetValue(clone, Vector2.zero); ScootPositionStartField?.SetValue(clone, Vector2.zero); ScootPositionPreviousField?.SetValue(clone, Vector2.zero); ScootPositionCurrentField?.SetValue(clone, Vector2.zero); ScootTimerField?.SetValue(clone, -123f); PreviousScootTimerField?.SetValue(clone, -123f); ScootAnimationEvaluationField?.SetValue(clone, 0f); ScootEvaluationField?.SetValue(clone, 0f); } private static void PositionStartedSlot(InventorySpot slot, float desiredX) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_005f: 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_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)slot == (Object)null) { return; } Transform transform = ((Component)slot).transform; Vector3 val = (Vector3)((InitialPositionField == null) ? transform.localPosition : ((Vector3)InitialPositionField.GetValue(slot))); val.x = desiredX; InitialPositionField?.SetValue(slot, val); if (!((SemiUI)slot).animateTheEntireObject) { Vector3 localPosition = transform.localPosition; transform.localPosition = new Vector3(desiredX, localPosition.y, localPosition.z); return; } float num = desiredX - ((SemiUI)slot).showPosition.x; if (!(Mathf.Abs(num) < 0.001f)) { ((SemiUI)slot).showPosition = ((SemiUI)slot).showPosition + new Vector2(num, 0f); ((SemiUI)slot).hidePosition = ((SemiUI)slot).hidePosition + new Vector2(num, 0f); if (HidePositionCurrentField?.GetValue(slot) is Vector2 val2) { HidePositionCurrentField.SetValue(slot, val2 + new Vector2(num, 0f)); } Vector3 localPosition2 = transform.localPosition; transform.localPosition = new Vector3(localPosition2.x + num, localPosition2.y, localPosition2.z); } } private static void ForceSlotShown(InventorySpot slot) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)slot == (Object)null)) { ((SemiUI)slot).Show(); HidePositionCurrentField?.SetValue(slot, ((SemiUI)slot).showPosition); HideTimerField?.SetValue(slot, 0f); ShowTimerField?.SetValue(slot, 0.1f); PreviousHideTimerField?.SetValue(slot, 0f); PreviousShowTimerField?.SetValue(slot, 0.1f); Vector3 val = Vector2.op_Implicit(((SemiUI)slot).showPosition); if (((SemiUI)slot).animateTheEntireObject) { ((Component)slot).transform.localPosition = new Vector3(val.x, val.y, ((Component)slot).transform.localPosition.z); } else if ((Object)(object)((SemiUI)slot).textRectTransform != (Object)null) { ((SemiUI)slot).textRectTransform.localPosition = new Vector3(val.x, val.y, ((SemiUI)slot).textRectTransform.localPosition.z); } } } private static void SetKeyLabel(Transform slotTransform, InventorySpot slot, int index) { string text = ((index == 9) ? "0" : (index + 1).ToString()); Transform obj = slotTransform.Find("Numbers"); TextMeshProUGUI val = ((obj != null) ? ((Component)obj).GetComponent<TextMeshProUGUI>() : null); if ((Object)(object)val != (Object)null) { ((TMP_Text)val).text = text; } if ((Object)(object)slot.noItem != (Object)null) { ((TMP_Text)slot.noItem).text = text; } } } [BepInPlugin("mathe.inventoryslotupgrade", "Inventory Slot Upgrade", "0.1.9")] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class Plugin : BaseUnityPlugin { public const string PluginGuid = "mathe.inventoryslotupgrade"; public const string PluginName = "Inventory Slot Upgrade"; public const string PluginVersion = "0.1.9"; public const string RepoLibGuid = "REPOLib"; public const string UpgradeId = "InventorySlot"; public const int BaseSlotCount = 3; public const int MinimumConfigurablePrice = 100000; public const int MaximumConfigurablePrice = 1000000; public const int PriceStep = 10000; public const float VanillaShopValueMultiplier = 4f; internal static readonly string[] PriceOptions = BuildPriceOptions(); private Harmony _harmony; internal static Plugin Instance { get; private set; } internal static PlayerUpgrade SlotUpgrade { get; private set; } internal static Item UpgradeItemData { get; private set; } internal static ManualLogSource Log { get; private set; } internal ConfigEntry<string> MinimumPrice { get; private set; } internal ConfigEntry<string> MaximumPrice { get; private set; } internal ConfigEntry<int> MaximumSlots { get; private set; } internal ConfigEntry<int> MaxAmountInShop { get; private set; } internal ConfigEntry<bool> AllowTeamUpgrades { get; private set; } internal static int EffectiveMaximumSlots => Mathf.Clamp(Instance?.MaximumSlots.Value ?? 10, 4, 10); internal static bool TeamUpgradesEnabled => Instance?.AllowTeamUpgrades.Value ?? false; internal static float EffectiveMinimumPrice => ParseConfiguredPrice(Instance?.MinimumPrice.Value, 100000); internal static float EffectiveMaximumPrice => Mathf.Clamp(ParseConfiguredPrice(Instance?.MaximumPrice.Value, 100000), EffectiveMinimumPrice, 1000000f); private void Awake() { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Expected O, but got Unknown //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Expected O, but got Unknown //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Expected O, but got Unknown //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Expected O, but got Unknown //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; MinimumPrice = ((BaseUnityPlugin)this).Config.Bind<string>("Shop", "Minimum Price", "100000", new ConfigDescription("Minimum displayed shop price. The arrows change it in 10,000-dollar steps.", (AcceptableValueBase)(object)new AcceptableValueList<string>(PriceOptions), Array.Empty<object>())); MaximumPrice = ((BaseUnityPlugin)this).Config.Bind<string>("Shop", "Maximum Price", "100000", new ConfigDescription("Maximum displayed shop price. The arrows change it in 10,000-dollar steps. Values below Minimum Price use Minimum Price.", (AcceptableValueBase)(object)new AcceptableValueList<string>(PriceOptions), Array.Empty<object>())); MaxAmountInShop = ((BaseUnityPlugin)this).Config.Bind<int>("Shop", "Max Amount In Shop", 1, new ConfigDescription("Maximum number of Inventory Slot Upgrade boxes that can appear in one shop.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 4), Array.Empty<object>())); MaximumSlots = ((BaseUnityPlugin)this).Config.Bind<int>("Upgrade", "Maximum Slots", 10, new ConfigDescription("Maximum usable inventory slots. Slots 4-10 use keys 4-9 and 0.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(4, 10), Array.Empty<object>())); AllowTeamUpgrades = ((BaseUnityPlugin)this).Config.Bind<bool>("Upgrade", "Allow Team Upgrades", false, "Whether activating the upgrade grants one inventory slot to every current player instead of only the player using it. All players should use the same setting."); UpgradeItemData = UpgradeItemFactory.CreateItemData(); MinimumPrice.SettingChanged += OnItemConfigurationChanged; MaximumPrice.SettingChanged += OnItemConfigurationChanged; MaxAmountInShop.SettingChanged += OnItemConfigurationChanged; MaximumSlots.SettingChanged += OnMaximumSlotsChanged; SlotUpgrade = Upgrades.RegisterUpgrade("InventorySlot", UpgradeItemData, (Action<PlayerAvatar, int>)InventorySlotController.ApplyUpgradeLevel, (Action<PlayerAvatar, int>)InventorySlotController.ApplyUpgradeLevel); if (SlotUpgrade == null) { ((BaseUnityPlugin)this).Logger.LogError((object)"Could not register REPOLib upgrade 'InventorySlot'. The plugin will not continue."); return; } _harmony = new Harmony("mathe.inventoryslotupgrade"); _harmony.PatchAll(); ((MonoBehaviour)this).StartCoroutine(SharedUpgradesPlusCompatibility.InstallWhenReady(_harmony)); ((MonoBehaviour)this).StartCoroutine(UpgradeItemFactory.RegisterPrefabWhenReady()); if (Chainloader.PluginInfos.ContainsKey("nickklmao.moreinventoryslots") || Chainloader.PluginInfos.ContainsKey("com.hiarlyscripter.bagexpander")) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"A fixed-count inventory slot mod is also loaded. Disable it to avoid duplicate UI and competing slot limits."); } ((BaseUnityPlugin)this).Logger.LogInfo((object)"Inventory Slot Upgrade initialized. Waiting for the vanilla upgrade prefab."); } private void OnDestroy() { if (MinimumPrice != null) { MinimumPrice.SettingChanged -= OnItemConfigurationChanged; } if (MaximumPrice != null) { MaximumPrice.SettingChanged -= OnItemConfigurationChanged; } if (MaxAmountInShop != null) { MaxAmountInShop.SettingChanged -= OnItemConfigurationChanged; } if (MaximumSlots != null) { MaximumSlots.SettingChanged -= OnMaximumSlotsChanged; } Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } } private void OnItemConfigurationChanged(object sender, EventArgs args) { UpgradeItemFactory.ApplyConfiguredValues(UpgradeItemData); } private void OnMaximumSlotsChanged(object sender, EventArgs args) { UpgradeItemFactory.ApplyConfiguredValues(UpgradeItemData); InventorySlotController.RequestRefresh(); } private static string[] BuildPriceOptions() { List<string> list = new List<string>(); for (int i = 100000; i <= 1000000; i += 10000) { list.Add(i.ToString(CultureInfo.InvariantCulture)); } return list.ToArray(); } private static float ParseConfiguredPrice(string rawValue, int fallback) { if (!float.TryParse(rawValue, NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { result = fallback; } result = Mathf.Clamp(result, 100000f, 1000000f); return Mathf.Round(result / 10000f) * 10000f; } } [HarmonyPatch] internal static class SaveLoadRecovery { [HarmonyPatch(typeof(StatsManager), "LoadGame")] private static class LoadGameDiagnostics { [HarmonyPrefix] private static void Prefix(string fileName) { Plugin.Log.LogInfo((object)("Loading save data '" + fileName + "'...")); } [HarmonyPostfix] private static void Postfix(StatsManager __instance, string fileName) { bool boolean = GetBoolean(SaveFileReadyField, __instance); Plugin.Log.LogInfo((object)$"Loaded save data '{fileName}'. Ready={boolean}."); } [HarmonyFinalizer] private static Exception Finalizer(Exception __exception, string fileName) { if (__exception != null) { Plugin.Log.LogError((object)$"Save data load '{fileName}' failed: {__exception}"); } return __exception; } } private static readonly FieldInfo RestartingField = AccessTools.Field(typeof(RunManager), "restarting"); private static readonly FieldInfo RestartingDoneField = AccessTools.Field(typeof(RunManager), "restartingDone"); private static readonly FieldInfo WaitToChangeSceneField = AccessTools.Field(typeof(RunManager), "waitToChangeScene"); private static readonly FieldInfo LobbyJoinField = AccessTools.Field(typeof(RunManager), "lobbyJoin"); private static readonly FieldInfo SaveFileReadyField = AccessTools.Field(typeof(StatsManager), "saveFileReady"); [HarmonyPrefix] [HarmonyPatch(typeof(SemiFunc), "MenuActionSingleplayerGame")] private static void BeforeSingleplayerLoad(string saveFileName) { PrepareMainMenuForLoad(saveFileName); } [HarmonyPrefix] [HarmonyPatch(typeof(SemiFunc), "MenuActionHostGame")] private static void BeforePrivateGameLoad(string saveFileName) { PrepareMainMenuForLoad(saveFileName); } private static void PrepareMainMenuForLoad(string saveFileName) { RunManager instance = RunManager.instance; if (!string.IsNullOrEmpty(saveFileName) && !((Object)(object)instance == (Object)null) && SemiFunc.IsMainMenu()) { bool num = GetBoolean(RestartingField, instance) || GetBoolean(RestartingDoneField, instance) || GetBoolean(WaitToChangeSceneField, instance) || GetBoolean(LobbyJoinField, instance); RestartingField?.SetValue(instance, false); RestartingDoneField?.SetValue(instance, false); WaitToChangeSceneField?.SetValue(instance, false); LobbyJoinField?.SetValue(instance, false); if (num) { Plugin.Log.LogWarning((object)("Cleared stale main-menu transition state before loading save '" + saveFileName + "'.")); } } } private static bool GetBoolean(FieldInfo field, object instance) { object obj = field?.GetValue(instance); bool flag = default(bool); int num; if (obj is bool) { flag = (bool)obj; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } } internal static class SharedUpgradesPlusCompatibility { private const string PluginGuid = "Vippy.SharedUpgradesPlus"; private const string CompatibilityTypeName = "SharedUpgradesPlus.Services.CompatibilityService"; private static bool _installed; internal static IEnumerator InstallWhenReady(Harmony harmony) { if (!Chainloader.PluginInfos.ContainsKey("Vippy.SharedUpgradesPlus")) { yield break; } for (int attempt = 0; attempt < 120; attempt++) { if (_installed) { break; } Type type = AccessTools.TypeByName("SharedUpgradesPlus.Services.CompatibilityService"); MethodInfo methodInfo = ((type == null) ? null : AccessTools.Method(type, "IsSharedByMoreUpgrades", (Type[])null, (Type[])null)); if (methodInfo != null) { MethodInfo methodInfo2 = AccessTools.Method(typeof(SharedUpgradesPlusCompatibility), "OverrideDoubleShareCheck", (Type[])null, (Type[])null); harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); _installed = true; Plugin.Log.LogInfo((object)"SharedUpgradesPlus compatibility enabled: InventorySlot will not be distributed twice when Allow Team Upgrades is on."); yield break; } yield return null; } if (!_installed) { Plugin.Log.LogWarning((object)"SharedUpgradesPlus is installed, but its double-share compatibility hook could not be found."); } } private static void OverrideDoubleShareCheck(string upgradeKey, ref bool __result) { if (Plugin.TeamUpgradesEnabled && !string.IsNullOrEmpty(upgradeKey) && upgradeKey.EndsWith("InventorySlot", StringComparison.OrdinalIgnoreCase)) { __result = true; } } } internal sealed class UpgradeBoxBridge : MonoBehaviour { private static readonly FieldInfo UpgradeIdField = AccessTools.Field(typeof(REPOLibItemUpgrade), "_upgradeId"); private static readonly FieldInfo TogglePlayerPhotonIdField = AccessTools.Field(typeof(ItemToggle), "playerTogglePhotonID"); private ItemToggle _itemToggle; private REPOLibItemUpgrade _repoLibUpgrade; private void Awake() { //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Expected O, but got Unknown //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Expected O, but got Unknown ItemUpgrade component = ((Component)this).GetComponent<ItemUpgrade>(); _itemToggle = ((Component)this).GetComponent<ItemToggle>(); _repoLibUpgrade = ((Component)this).GetComponent<REPOLibItemUpgrade>(); if ((Object)(object)component == (Object)null || (Object)(object)_itemToggle == (Object)null || (Object)(object)_repoLibUpgrade == (Object)null || UpgradeIdField == null || TogglePlayerPhotonIdField == null) { Plugin.Log.LogError((object)"Spawned Inventory Slot Upgrade is missing its upgrade components."); return; } UpgradeIdField.SetValue(_repoLibUpgrade, "InventorySlot"); ItemUpgrade val = component; if (val.upgradeEvent == null) { val.upgradeEvent = new UnityEvent(); } ((UnityEventBase)component.upgradeEvent).RemoveAllListeners(); component.upgradeEvent.AddListener(new UnityAction(ApplyUpgrade)); } private void ApplyUpgrade() { if (!Plugin.TeamUpgradesEnabled) { _repoLibUpgrade.Upgrade(); return; } int num = (int)TogglePlayerPhotonIdField.GetValue(_itemToggle); PlayerAvatar val = SemiFunc.PlayerAvatarGetFromPhotonID(num); if ((Object)(object)val == (Object)null) { Plugin.Log.LogError((object)$"Could not apply the shared Inventory Slot Upgrade: player photon ID {num} was not found."); } else { if (SemiFunc.IsMultiplayer() && ((Object)(object)val.photonView == (Object)null || !val.photonView.IsMine)) { return; } int num2 = Plugin.EffectiveMaximumSlots - 3; int num3 = 0; HashSet<string> hashSet = new HashSet<string>(); foreach (PlayerAvatar item in SemiFunc.PlayerGetAll()) { if (!((Object)(object)item == (Object)null)) { string text = SemiFunc.PlayerGetSteamID(item); if (!string.IsNullOrEmpty(text) && hashSet.Add(text) && Plugin.SlotUpgrade.GetLevel(text) < num2) { Plugin.SlotUpgrade.AddLevel(item, 1); num3++; } } } Plugin.Log.LogInfo((object)("Shared Inventory Slot Upgrade activated by " + SemiFunc.PlayerGetName(val) + "; " + $"granted one level to {num3} current player(s), capped at {Plugin.EffectiveMaximumSlots} slots.")); } } } internal static class UpgradeDecal { private const string ResourceName = "InventorySlotUpgrade.Assets.InventorySlotUpgrade_Albedo.png"; private const string VanillaTextureName = "Upgrade_Health_Albedo"; private static Texture2D _texture; internal static bool Apply(GameObject prefab) { //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Expected O, but got Unknown //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)prefab == (Object)null) { return false; } Texture2D val = LoadTexture(); if ((Object)(object)val == (Object)null) { return false; } int num = 0; Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(true); foreach (Renderer val2 in componentsInChildren) { Material[] sharedMaterials = val2.sharedMaterials; bool flag = false; for (int j = 0; j < sharedMaterials.Length; j++) { Material val3 = sharedMaterials[j]; if (UsesVanillaHealthTexture(val3)) { if ((Object)(object)val3.mainTexture != (Object)null) { ((Texture)val).filterMode = val3.mainTexture.filterMode; ((Texture)val).wrapMode = val3.mainTexture.wrapMode; ((Texture)val).anisoLevel = val3.mainTexture.anisoLevel; } Material val4 = new Material(val3) { name = ((Object)val3).name + " - Inventory Slot Upgrade", mainTexture = (Texture)(object)val }; sharedMaterials[j] = val4; flag = true; num++; } } if (flag) { val2.sharedMaterials = sharedMaterials; } } if (num == 0) { Plugin.Log.LogWarning((object)"Could not find a prefab material using 'Upgrade_Health_Albedo'. The vanilla health decal will remain visible."); return false; } Plugin.Log.LogInfo((object)$"Applied the embedded inventory-slot decal to {num} prefab material(s)."); return true; } private static bool UsesVanillaHealthTexture(Material material) { if ((Object)(object)material == (Object)null || (Object)(object)material.mainTexture == (Object)null) { return false; } return ((Object)material.mainTexture).name.IndexOf("Upgrade_Health_Albedo", StringComparison.OrdinalIgnoreCase) >= 0; } private static Texture2D LoadTexture() { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Expected O, but got Unknown if ((Object)(object)_texture != (Object)null) { return _texture; } using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("InventorySlotUpgrade.Assets.InventorySlotUpgrade_Albedo.png"); if (stream == null) { Plugin.Log.LogError((object)"Embedded decal resource 'InventorySlotUpgrade.Assets.InventorySlotUpgrade_Albedo.png' was not found."); return null; } using MemoryStream memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false) { name = "InventorySlotUpgrade_Albedo" }; if (!ImageConversion.LoadImage(val, memoryStream.ToArray(), false)) { Object.Destroy((Object)(object)val); Plugin.Log.LogError((object)"Unity could not decode the embedded inventory-slot decal PNG."); return null; } _texture = val; return _texture; } } [HarmonyPatch(typeof(StatsManager), "RunStartStats")] internal static class UpgradeDisplayPatch { private static readonly FieldInfo UpgradesInfoField = AccessTools.Field(typeof(StatsManager), "upgradesInfo"); [HarmonyPostfix] private static void AddDisplayName(StatsManager __instance) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown if (UpgradesInfoField.GetValue(__instance) is Dictionary<string, UpgradeInfo> dictionary) { dictionary["playerUpgradeInventorySlot"] = new UpgradeInfo { displayName = "Inventory Slots" }; } } } internal static class UpgradeItemFactory { internal const string AssetName = "InventorySlotUpgrade"; internal const string DisplayName = "Inventory Slot Upgrade"; private const string VanillaTemplateName = "Item Upgrade Player Health"; private static GameObject _prefabRoot; internal static Item CreateItemData() { //IL_0028: 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_0037: Unknown result type (might be due to invalid IL or missing references) Item obj = ScriptableObject.CreateInstance<Item>(); ((Object)obj).name = "InventorySlotUpgrade"; obj.itemName = "Inventory Slot Upgrade"; obj.description = "Adds one inventory slot."; obj.itemType = (itemType)3; obj.emojiIcon = (emojiIcon)11; obj.itemVolume = (itemVolume)6; obj.value = ScriptableObject.CreateInstance<Value>(); obj.minPlayerCount = 1; obj.maxPurchase = true; obj.physicalItem = true; ApplyConfiguredValues(obj); return obj; } internal static void ApplyConfiguredValues(Item item) { if (!((Object)(object)item == (Object)null)) { if ((Object)(object)item.value == (Object)null) { item.value = ScriptableObject.CreateInstance<Value>(); } int num = Plugin.EffectiveMaximumSlots - 3; item.value.valueMin = Plugin.EffectiveMinimumPrice / 4f; item.value.valueMax = Plugin.EffectiveMaximumPrice / 4f; item.maxAmount = num; item.maxAmountInShop = Mathf.Clamp(Plugin.Instance?.MaxAmountInShop.Value ?? 1, 1, 4); item.maxPurchaseAmount = num; } } internal static IEnumerator RegisterPrefabWhenReady() { Item template = null; int waits = 0; while ((Object)(object)template == (Object)null) { template = ((IEnumerable<Item>)Items.AllItems).FirstOrDefault((Func<Item, bool>)((Item item) => (Object)(object)item != (Object)null && ((Object)item).name == "Item Upgrade Player Health" && item.prefab != null && (Object)(object)((PrefabRef<GameObject>)(object)item.prefab).Prefab != (Object)null)); if ((Object)(object)template == (Object)null) { waits++; if (waits == 120) { Plugin.Log.LogWarning((object)"Still waiting for vanilla prefab 'Item Upgrade Player Health'. Registration will keep retrying."); } yield return (object)new WaitForSeconds(0.25f); } } CopyTemplateMetadata(template, Plugin.UpgradeItemData); _prefabRoot = new GameObject("Inventory Slot Upgrade - Registered Prefabs"); _prefabRoot.SetActive(false); Object.DontDestroyOnLoad((Object)(object)_prefabRoot); GameObject val = Object.Instantiate<GameObject>(((PrefabRef<GameObject>)(object)template.prefab).Prefab, _prefabRoot.transform, false); ((Object)val).name = "InventorySlotUpgrade"; UpgradeDecal.Apply(val); ItemAttributes component = val.GetComponent<ItemAttributes>(); ItemUpgrade component2 = val.GetComponent<ItemUpgrade>(); ItemToggle component3 = val.GetComponent<ItemToggle>(); if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null || (Object)(object)component3 == (Object)null) { Plugin.Log.LogError((object)"The vanilla health-upgrade prefab no longer has the expected ItemAttributes, ItemUpgrade, and ItemToggle components."); Object.Destroy((Object)(object)_prefabRoot); _prefabRoot = null; yield break; } component.item = Plugin.UpgradeItemData; component2.isPlayerUpgrade = true; component2.upgradeEvent = new UnityEvent(); REPOLibItemUpgrade val2 = val.GetComponent<REPOLibItemUpgrade>(); if ((Object)(object)val2 == (Object)null) { val2 = val.AddComponent<REPOLibItemUpgrade>(); } AccessTools.Field(typeof(REPOLibItemUpgrade), "_upgradeId").SetValue(val2, "InventorySlot"); if ((Object)(object)val.GetComponent<UpgradeBoxBridge>() == (Object)null) { val.AddComponent<UpgradeBoxBridge>(); } if (Items.RegisterItem(component) == null) { Plugin.Log.LogError((object)"REPOLib rejected the Inventory Slot Upgrade item prefab."); } else { Plugin.Log.LogInfo((object)("Registered '" + Plugin.UpgradeItemData.itemName + "' from vanilla prefab 'Item Upgrade Player Health' " + $"with a displayed price range of {Plugin.EffectiveMinimumPrice:0}-{Plugin.EffectiveMaximumPrice:0}.")); } } private static void CopyTemplateMetadata(Item source, Item destination) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) destination.disabled = false; destination.itemType = (itemType)3; destination.emojiIcon = source.emojiIcon; destination.itemVolume = source.itemVolume; destination.itemSecretShopType = source.itemSecretShopType; destination.colorPreset = source.colorPreset; destination.spawnRotationOffset = source.spawnRotationOffset; destination.physicalItem = source.physicalItem; } } [HarmonyPatch(typeof(ShopManager), "UpgradeValueGet")] internal static class UpgradePricePatch { [HarmonyPrefix] [HarmonyPriority(800)] private static bool Prefix(float _value, Item item, ref float __result) { if ((Object)(object)item == (Object)null || ((Object)item).name != "InventorySlotUpgrade") { return true; } __result = Mathf.Ceil(_value); return false; } } }