The BepInEx console will not appear when launching like it does for other games on Thunderstore (you can turn it back on in your BepInEx.cfg file). If your PEAK crashes on startup, add -dx12 to your launch parameters.
Decompiled source of ItemScroller v1.0.2
ItemScroller.dll
Decompiled a day agousing System; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using ItemScroller.Patches; using Microsoft.CodeAnalysis; using UnityEngine; using Zorro.ControllerSupport; using Zorro.Core; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: AssemblyCompany("ItemScroller")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+622039bb71260ed16b1edef318d7aa0f41bb2918")] [assembly: AssemblyProduct("ItemScroller")] [assembly: AssemblyTitle("ItemScroller")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace ItemScroller { [BepInPlugin("MasterAli2.ItemScroller", "Item Scroller", "1.0.0")] public class ItemScroller : BaseUnityPlugin { public const string GUID = "MasterAli2.ItemScroller"; public const string NAME = "Item Scroller"; public const string VERSION = "1.0.0"; public ConfigEntry<float> ScrollThreshold; public ConfigEntry<float> MaxHoldTimeForScrollables; internal static ManualLogSource Logger { get; private set; } internal static Harmony? Harmony { get; set; } public static ItemScroller Instance { get; private set; } private void Awake() { Logger = ((BaseUnityPlugin)this).Logger; Instance = this; Patch(); ScrollThreshold = ((BaseUnityPlugin)this).Config.Bind<float>("Scrolling", "ScrollThreshold", 0.75f, "The minimum amount of scroll before being able to scroll beetween items"); MaxHoldTimeForScrollables = ((BaseUnityPlugin)this).Config.Bind<float>("Scrolling", "MaxHoldTime", 0.75f, "The time (in seconds) that an item with a scroll function must be held before it cant be scrolled away from"); Logger.LogInfo((object)"MasterAli2.ItemScroller v1.0.0 has loaded!"); } internal static void Patch() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown if (Harmony == null) { Harmony = new Harmony("MasterAli2.ItemScroller"); } Logger.LogDebug((object)"Patching..."); Harmony.PatchAll(typeof(General)); Logger.LogDebug((object)"Finished patching!"); } } } namespace ItemScroller.Patches { internal class General { private static float lastScrolled; [HarmonyPatch(typeof(CharacterItems), "DoSwitching")] [HarmonyPrefix] private static void _(CharacterItems __instance) { //IL_01eb: Unknown result type (might be due to invalid IL or missing references) if (!__instance.character.IsLocal) { return; } lastScrolled = Mathf.Clamp(lastScrolled - Time.deltaTime, 0f, ItemScroller.Instance.MaxHoldTimeForScrollables.Value); if (!__instance.character.IsLocal || !__instance.character.CanDoInput() || !(Time.time > __instance.lastEquippedSlotTime + __instance.equippedSlotCooldown) || __instance.character.data.isClimbing || __instance.character.data.isRopeClimbing || __instance.character.data.fullyPassedOut) { return; } if (Object.op_Implicit((Object)(object)__instance.character.data.currentItem) && !__instance.character.data.passedOut) { Item currentItem = __instance.character.data.currentItem; if (!hasScrollFunction(currentItem)) { } } float scrollInput = __instance.character.input.scrollInput; if (scrollInput != 0f && Mathf.Abs(scrollInput) >= ItemScroller.Instance.ScrollThreshold.Value) { bool forward = true; if (Mathf.Sign(scrollInput) == 1f) { forward = false; } (byte?, bool) tuple = Next(forward, __instance.lastSelectedSlot.Value, __instance); var (b, _) = tuple; if (!tuple.Item2 || !b.HasValue) { ItemScroller.Logger.LogDebug((object)"No empty slot found"); return; } __instance.lastSwitched = Time.time; __instance.timesSwitchedRecently++; lastScrolled = ItemScroller.Instance.MaxHoldTimeForScrollables.Value; __instance.EquipSlot(Optionable<byte>.Some(b.Value)); } } private static bool hasScrollFunction(Item? item) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Invalid comparison between Unknown and I4 if ((Object)(object)item == (Object)null) { return false; } bool flag = (int)InputHandler.GetCurrentUsedInputScheme() == 0; if (item.OnScrolled != null || (flag && item.OnScrolledMouseOnly != null)) { return true; } ItemComponent[] itemComponents = item.itemComponents; foreach (ItemComponent val in itemComponents) { if (val is RopeSpool) { return true; } } return false; } private static ItemSlot? getItemSlot(byte slot, CharacterItems instance) { if (!ArrayExtensions.WithinRange<ItemSlot>(instance.character.player.itemSlots, (int)slot)) { return null; } return instance.character.player.itemSlots[slot]; } public static (byte?, bool) Next(bool forward, byte target, CharacterItems instance) { CharacterItems instance2 = instance; if (lastScrolled == 0f && hasScrollFunction(instance2.character.data.currentItem)) { return (null, false); } bool hasBackPack = !instance2.character.player.GetItemSlot((byte)3).IsEmpty(); byte b = (byte)(hasBackPack ? 4u : 3u); if (target >= b || (target == 3 && !hasBackPack)) { target = 0; } byte b2 = target; int num = 0; int num2 = b + 1; do { b2 = ((!forward) ? ((byte)((b2 - 1 + b) % b)) : ((byte)((b2 + 1) % b))); if (b2 == 3 && !hasBackPack) { num++; continue; } if (IsValidSlot(b2) && target != b2) { return (b2, true); } num++; } while (num < num2); return (null, false); bool IsValidSlot(byte slot) { if (slot == 3) { return hasBackPack; } if (slot >= 3) { return false; } ItemSlot itemSlot = getItemSlot(slot, instance2); if (itemSlot.IsEmpty()) { return false; } return true; } } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }