Decompiled source of ReservedItemSlotCore PlusNonScrapSlots v1.0.6
BepInEx/plugins/ReservedItemSlotCore.dll
Decompiled 4 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using GameNetcodeStuff; using HarmonyLib; using ReservedItemSlotCore.Compatibility; using ReservedItemSlotCore.Config; using ReservedItemSlotCore.Data; using ReservedItemSlotCore.Input; using ReservedItemSlotCore.Networking; using ReservedItemSlotCore.Patches; using TMPro; using TooManyEmotes; using TooManyEmotes.Patches; using TooManyEmotes.UI; using Unity.Collections; using Unity.Netcode; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("ReservedItemSlotCore")] [assembly: AssemblyDescription("Mod made by flipf17")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("ReservedItemSlotCore")] [assembly: AssemblyCopyright("Copyright © 2023")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("238ce080-e339-46b6-9b08-992a950453a1")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: InternalsVisibleTo("ReservedFlashlightSlot")] [assembly: InternalsVisibleTo("ReservedWalkieSlot")] [assembly: InternalsVisibleTo("ReservedWeaponSlot")] [assembly: InternalsVisibleTo("ReservedSprayPaintSlot")] [assembly: InternalsVisibleTo("ReservedUtilitySlot")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("1.0.0.0")] internal static class LethalConfigHelper { private static bool _registered = false; private static readonly Dictionary<ConfigEntryBase, object> _lcTxtOptsByEntry = new Dictionary<ConfigEntryBase, object>(); private static readonly Dictionary<ConfigEntryBase, object> _lcTxtItemByEntry = new Dictionary<ConfigEntryBase, object>(); internal static void TryRegisterColorDisplay(ConfigEntry<string> colorEntry, string effectiveHex) { Type type = Type.GetType("LethalConfig.LethalConfigManager, LethalConfig"); if (type == null) { return; } try { string text = "Current saved color:\n<b>" + effectiveHex + "</b>"; MethodInfo methodInfo = null; Type type2 = Type.GetType("LethalConfig.ConfigItems.BaseConfigItem, LethalConfig"); if (type2 != null) { methodInfo = type.GetMethod("AddConfigItem", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { type2 }, null); } if (methodInfo == null) { methodInfo = Array.Find(type.GetMethods(BindingFlags.Static | BindingFlags.Public), (MethodInfo m) => m.Name == "AddConfigItem" && m.GetParameters().Length == 1); } bool flag = false; if (!_registered) { Type type3 = Type.GetType("LethalConfig.ConfigItems.Options.TextInputFieldOptions, LethalConfig"); Type type4 = Type.GetType("LethalConfig.ConfigItems.TextInputFieldConfigItem, LethalConfig"); if (type3 != null && type4 != null && methodInfo != null) { object obj = Activator.CreateInstance(type3); type3.GetProperty("Section")?.SetValue(obj, ((ConfigEntryBase)colorEntry).Definition.Section); type3.GetProperty("Name")?.SetValue(obj, ((ConfigEntryBase)colorEntry).Definition.Key); ConfigDescription description = ((ConfigEntryBase)colorEntry).Description; string text2 = ((description != null) ? description.Description : null) ?? ""; type3.GetProperty("Description")?.SetValue(obj, string.IsNullOrWhiteSpace(text2) ? text : (text2 + "\n\n" + text)); type3.GetProperty("RequiresRestart")?.SetValue(obj, false); object obj2 = Activator.CreateInstance(type4, colorEntry, obj); methodInfo.Invoke(null, new object[1] { obj2 }); flag = true; _lcTxtOptsByEntry[(ConfigEntryBase)(object)colorEntry] = obj; _lcTxtItemByEntry[(ConfigEntryBase)(object)colorEntry] = obj2; } } else { if (_lcTxtOptsByEntry.TryGetValue((ConfigEntryBase)(object)colorEntry, out var value)) { ConfigDescription description2 = ((ConfigEntryBase)colorEntry).Description; string text3 = ((description2 != null) ? description2.Description : null) ?? ""; string value2 = (string.IsNullOrWhiteSpace(text3) ? text : (text3 + "\n\n" + text)); value.GetType().GetProperty("Description")?.SetValue(value, value2); if (_lcTxtItemByEntry.TryGetValue((ConfigEntryBase)(object)colorEntry, out var value3)) { value3.GetType().GetMethod("ApplyChanges", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.Invoke(value3, null); } } else { Type type5 = Type.GetType("LethalConfig.ConfigItems.Options.TextInputFieldOptions, LethalConfig"); Type type6 = Type.GetType("LethalConfig.ConfigItems.TextInputFieldConfigItem, LethalConfig"); if (type5 != null && type6 != null && methodInfo != null) { object obj3 = Activator.CreateInstance(type5); type5.GetProperty("Section")?.SetValue(obj3, ((ConfigEntryBase)colorEntry).Definition.Section); type5.GetProperty("Name")?.SetValue(obj3, ((ConfigEntryBase)colorEntry).Definition.Key); ConfigDescription description3 = ((ConfigEntryBase)colorEntry).Description; string text4 = ((description3 != null) ? description3.Description : null) ?? ""; string value4 = (string.IsNullOrWhiteSpace(text4) ? text : (text4 + "\n\n" + text)); type5.GetProperty("Description")?.SetValue(obj3, value4); type5.GetProperty("RequiresRestart")?.SetValue(obj3, false); object obj4 = Activator.CreateInstance(type6, colorEntry, obj3); methodInfo.Invoke(null, new object[1] { obj4 }); _lcTxtOptsByEntry[(ConfigEntryBase)(object)colorEntry] = obj3; _lcTxtItemByEntry[(ConfigEntryBase)(object)colorEntry] = obj4; } else { Debug.LogWarning((object)"LethalConfig: cannot update description (no cache and no re-add path)."); } } flag = true; } if (flag) { _registered = true; type.GetMethod("SkipAutoGenFor", new Type[1] { typeof(ConfigEntryBase) })?.Invoke(null, new object[1] { colorEntry }); } else { Debug.Log((object)"LethalConfigHelper: Could not display currently active color."); } } catch (Exception arg) { Debug.Log((object)$"LethalConfig UI extras failed: {arg}"); } } } namespace ReservedItemSlotCore { [HarmonyPatch] internal static class ItemNameMap { private static Dictionary<string, Item> originalNameToItemMap = new Dictionary<string, Item>(); private static Dictionary<Item, string> itemToNameMap = new Dictionary<Item, string>(); [HarmonyPatch(typeof(StartOfRound), "Start")] [HarmonyPrefix] private static void RecordOriginalItemNames(StartOfRound __instance) { List<Item> list = __instance?.allItemsList?.itemsList; if (list == null) { Plugin.LogError("Failed to record original item names. This might be fine if you're not using translation/localization mods. (no guarantees)"); return; } foreach (Item item in list) { string text = item?.itemName; if (!string.IsNullOrEmpty(text)) { if (!itemToNameMap.ContainsKey(item)) { itemToNameMap.Add(item, text); } if (!originalNameToItemMap.ContainsKey(text)) { originalNameToItemMap.Add(text, item); } } } } internal static string GetItemName(GrabbableObject grabbableObject) { if ((Object)(object)grabbableObject?.itemProperties == (Object)null) { return ""; } string itemName = GetItemName(grabbableObject.itemProperties); if (itemName == null) { return ""; } return itemName; } internal static string GetItemName(Item item) { if ((Object)(object)item == (Object)null) { return ""; } if (itemToNameMap.TryGetValue(item, out var value) && value != null) { return value; } return ""; } internal static bool IsZeroValueScrap(GrabbableObject grabbable) { if ((Object)(object)grabbable == (Object)null || (Object)(object)grabbable.itemProperties == (Object)null) { return false; } try { return !grabbable.itemProperties.isScrap || (grabbable.itemProperties.isScrap && grabbable.scrapValue == 0); } catch { return false; } } } [BepInPlugin("FlipMods.ReservedItemSlotCore", "ReservedItemSlotCore", "2.0.52")] [BepInDependency(/*Could not decode attribute arguments.*/)] internal class Plugin : BaseUnityPlugin { private Harmony _harmony; public static Plugin instance; private static ManualLogSource logger; public static List<ReservedItemSlotData> customItemSlots = new List<ReservedItemSlotData>(); private void Awake() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown instance = this; CreateCustomLogger(); ConfigSettings.BindConfigSettings(); AddCustomItemSlots(); _harmony = new Harmony("ReservedItemSlotCore"); PatchAll(); Log("ReservedItemSlotCore loaded"); } private void AddCustomItemSlots() { //IL_005e: 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_006e: Unknown result type (might be due to invalid IL or missing references) foreach (CustomItemSlotConfigEntry customItemSlotConfig in ConfigSettings.customItemSlotConfigs) { if (!(customItemSlotConfig.customItemSlotName == "") && customItemSlotConfig.customItemSlotItems.Length != 0) { ReservedItemSlotData reservedItemSlotData = ReservedItemSlotData.CreateReservedItemSlotData(customItemSlotConfig.customItemSlotName, customItemSlotConfig.customItemSlotPriority, customItemSlotConfig.customItemSlotPrice); string[] customItemSlotItems = customItemSlotConfig.customItemSlotItems; for (int i = 0; i < customItemSlotItems.Length; i++) { ReservedItemData itemData = new ReservedItemData(customItemSlotItems[i]); reservedItemSlotData.AddItemToReservedItemSlot(itemData); } customItemSlots.Add(reservedItemSlotData); } } } private void PatchAll() { IEnumerable<Type> enumerable; try { enumerable = Assembly.GetExecutingAssembly().GetTypes(); } catch (ReflectionTypeLoadException ex) { enumerable = ex.Types.Where((Type t) => t != null); } foreach (Type item in enumerable) { try { _harmony.PatchAll(item); } catch { } } } private void CreateCustomLogger() { try { logger = Logger.CreateLogSource(string.Format("{0}-{1}", "ReservedItemSlotCore", "2.0.52")); } catch { logger = ((BaseUnityPlugin)this).Logger; } } public static void Log(string message) { logger.LogInfo((object)message); } public static void LogError(string message) { logger.LogError((object)message); } public static void LogWarning(string message) { logger.LogWarning((object)message); } public static void LogVerbose(string message) { if (ConfigSettings.verboseLogs.Value) { logger.LogInfo((object)("[VERBOSE] " + message)); } } public static void LogErrorVerbose(string message) { if (ConfigSettings.verboseLogs.Value) { logger.LogError((object)("[VERBOSE] " + message)); } } public static void LogWarningVerbose(string message) { if (ConfigSettings.verboseLogs.Value) { logger.LogWarning((object)("[VERBOSE] " + message)); } } public static bool IsModLoaded(string guid) { return Chainloader.PluginInfos.ContainsKey(guid); } } public static class PluginInfo { public const string PLUGIN_GUID = "FlipMods.ReservedItemSlotCore"; public const string PLUGIN_NAME = "ReservedItemSlotCore"; public const string PLUGIN_VERSION = "2.0.52"; } [HarmonyPatch] public static class ReservedHotbarManager { public static int indexInHotbar = 0; public static int indexInReservedHotbar = 0; internal static List<ReservedItemSlotData> currentlyToggledItemSlots = new List<ReservedItemSlotData>(); public static PlayerControllerB localPlayerController => StartOfRound.Instance?.localPlayerController; public static ReservedPlayerData localPlayerData => ReservedPlayerData.localPlayerData; public static int reservedHotbarSize => SessionManager.numReservedItemSlotsUnlocked; public static bool isToggledInReservedSlots { get { ReservedItemSlotData currentlySelectedReservedItemSlot = localPlayerData.GetCurrentlySelectedReservedItemSlot(); if (!ReservedPlayerData.localPlayerData.inReservedHotbarSlots || !Keybinds.pressedToggleKey) { if (currentlyToggledItemSlots != null && currentlySelectedReservedItemSlot != null) { return currentlyToggledItemSlots.Contains(currentlySelectedReservedItemSlot); } return false; } return true; } } [HarmonyPatch(typeof(StartOfRound), "Awake")] [HarmonyPrefix] public static void InitSession(StartOfRound __instance) { currentlyToggledItemSlots = new List<ReservedItemSlotData>(); ReservedPlayerData.allPlayerData.Clear(); indexInHotbar = 0; indexInReservedHotbar = -1; } public static void ForceToggleReservedHotbar(params ReservedItemSlotData[] reservedItemSlots) { if (((NetworkBehaviour)localPlayerController).IsOwner && localPlayerController.isPlayerControlled && (!((NetworkBehaviour)localPlayerController).IsServer || localPlayerController.isHostPlayerObject) && HUDPatcher.hasReservedItemSlotsAndEnabled && reservedHotbarSize > 0 && CanSwapHotbars() && reservedItemSlots != null && reservedItemSlots.Length != 0 && !((Object)(object)localPlayerController == (Object)null)) { currentlyToggledItemSlots = new List<ReservedItemSlotData>(reservedItemSlots); int num = currentlyToggledItemSlots.First().GetReservedItemSlotIndex() + localPlayerData.reservedHotbarStartIndex; bool active = ReservedPlayerData.localPlayerData.IsReservedItemSlot(num); if (currentlyToggledItemSlots.Contains(localPlayerData.GetCurrentlySelectedReservedItemSlot())) { FocusReservedHotbarSlots(active: false); return; } HUDPatcher.UpdateToggledReservedItemSlotsUI(); FocusReservedHotbarSlots(active, num); } } public static void FocusReservedHotbarSlots(bool active, int forceSlot = -1) { if (!HUDPatcher.hasReservedItemSlotsAndEnabled || (reservedHotbarSize <= 0 && active) || (ReservedPlayerData.localPlayerData.currentItemSlotIsReserved == active && (forceSlot == -1 || localPlayerData.currentItemSlot == forceSlot))) { return; } if (forceSlot != -1) { active = localPlayerData.IsReservedItemSlot(forceSlot); } ReservedPlayerData reservedPlayerData = ReservedPlayerData.localPlayerData; indexInHotbar = Mathf.Clamp(indexInHotbar, 0, localPlayerController.ItemSlots.Length - 1); indexInHotbar = ((!reservedPlayerData.IsReservedItemSlot(indexInHotbar)) ? indexInHotbar : 0); indexInReservedHotbar = Mathf.Clamp(indexInReservedHotbar, reservedPlayerData.reservedHotbarStartIndex, reservedPlayerData.reservedHotbarEndIndexExcluded - 1); int num = Mathf.Clamp(localPlayerController.currentItemSlot, 0, localPlayerController.ItemSlots.Length); int i = num; bool flag = active; if (flag && (!reservedPlayerData.IsReservedItemSlot(num) || forceSlot != -1)) { indexInHotbar = num; indexInHotbar = ((!reservedPlayerData.IsReservedItemSlot(indexInHotbar)) ? indexInHotbar : 0); if (forceSlot != -1 && reservedPlayerData.IsReservedItemSlot(forceSlot)) { indexInReservedHotbar = forceSlot; } i = indexInReservedHotbar; if (!AllowScrollCompat.Loaded && (Object)(object)localPlayerController.ItemSlots[i] == (Object)null && reservedPlayerData.GetNumHeldReservedItems() > 0) { for (i = reservedPlayerData.reservedHotbarStartIndex; i < reservedPlayerData.reservedHotbarEndIndexExcluded && !((Object)(object)localPlayerController.ItemSlots[i] != (Object)null); i++) { } } Plugin.LogVerbose("Focusing reserved hotbar slots. NewIndex: " + i + " OldIndex: " + num + " ReservedStartIndex: " + ReservedPlayerData.localPlayerData.reservedHotbarStartIndex); } else if (!flag && (ReservedPlayerData.localPlayerData.IsReservedItemSlot(num) || forceSlot != -1)) { indexInReservedHotbar = Mathf.Clamp(num, reservedPlayerData.reservedHotbarStartIndex, reservedPlayerData.reservedHotbarEndIndexExcluded - 1); if (forceSlot != -1 && !reservedPlayerData.IsReservedItemSlot(forceSlot)) { indexInHotbar = forceSlot; } i = indexInHotbar; Plugin.LogVerbose("Unfocusing reserved hotbar slots. NewIndex: " + i + " OldIndex: " + num + " ReservedStartIndex: " + ReservedPlayerData.localPlayerData.reservedHotbarStartIndex); } if (i < 0) { Plugin.LogError("Swapping to hotbar slot: " + i + ". Maybe send these logs to Flip? :)"); } else if (i >= localPlayerController.ItemSlots.Length) { Plugin.LogError("Swapping to hotbar slot: " + i + " InventorySize: " + localPlayerController.ItemSlots.Length + ". Maybe send these logs to Flip? :)"); } SyncManager.SwapHotbarSlot(i); if (localPlayerController.currentItemSlot != i) { Plugin.LogWarning("OnFocusReservedHotbarSlots - New hotbar index does not match target hotbar index. Tried to swap to index: " + i + " Current index: " + localPlayerController.currentItemSlot + " Tried swapping to reserved hotbar: " + active); } } public static bool CanSwapHotbars() { if (!HUDPatcher.hasReservedItemSlotsAndEnabled) { return false; } if (TooManyEmotes_Compat.Enabled && TooManyEmotes_Compat.IsLocalPlayerPerformingCustomEmote() && !TooManyEmotes_Compat.CanMoveWhileEmoting()) { return false; } if (ReservedPlayerData.localPlayerData.grabbingReservedItemData == null && !localPlayerController.isGrabbingObjectAnimation && !localPlayerController.quickMenuManager.isMenuOpen && !localPlayerController.inSpecialInteractAnimation && !localPlayerData.throwingObject && !localPlayerController.isTypingChat && !localPlayerController.twoHanded && !localPlayerController.activatingItem && !localPlayerController.jetpackControls && !localPlayerController.disablingJetpackControls && !localPlayerController.inTerminalMenu && !localPlayerController.isPlayerDead) { return !(localPlayerData.timeSinceSwitchingSlots < 0.3f); } return false; } internal static void OnSwapToReservedHotbar() { if (!localPlayerData.currentItemSlotIsReserved) { return; } if (localPlayerData.currentItemSlotIsReserved) { indexInReservedHotbar = localPlayerController.currentItemSlot; } ReservedItemSlotData currentlySelectedReservedItemSlot = localPlayerData.GetCurrentlySelectedReservedItemSlot(); if (isToggledInReservedSlots && currentlyToggledItemSlots != null && !currentlyToggledItemSlots.Contains(currentlySelectedReservedItemSlot)) { currentlyToggledItemSlots = null; } if (HUDPatcher.reservedItemSlots == null) { return; } foreach (Image reservedItemSlot in HUDPatcher.reservedItemSlots) { CanvasGroup component = ((Component)reservedItemSlot).GetComponent<CanvasGroup>(); if ((Object)(object)component != (Object)null) { component.ignoreParentGroups = !HUDPatcher.IsHudHidden; } } } internal static void OnSwapToVanillaHotbar() { if (localPlayerData.currentItemSlotIsReserved) { return; } if (!localPlayerData.currentItemSlotIsReserved) { indexInHotbar = localPlayerController.currentItemSlot; } currentlyToggledItemSlots = null; if (HUDPatcher.reservedItemSlots == null) { return; } foreach (Image reservedItemSlot in HUDPatcher.reservedItemSlots) { CanvasGroup component = ((Component)reservedItemSlot).GetComponent<CanvasGroup>(); if ((Object)(object)component != (Object)null) { component.ignoreParentGroups = ConfigSettings.preventReservedItemSlotFade.Value; } } } [HarmonyPatch(typeof(PlayerControllerB), "LateUpdate")] [HarmonyPrefix] private static void RefocusReservedHotbarAfterAnimation(PlayerControllerB __instance) { if (HUDPatcher.hasReservedItemSlotsAndEnabled && !((Object)(object)__instance != (Object)(object)localPlayerController) && !Keybinds.pressedToggleKey && Keybinds.holdingModifierKey != ReservedPlayerData.localPlayerData.currentItemSlotIsReserved && !isToggledInReservedSlots && CanSwapHotbars()) { FocusReservedHotbarSlots(Keybinds.holdingModifierKey); } } [HarmonyPatch(typeof(PlayerControllerB), "UpdateSpecialAnimationValue")] [HarmonyPostfix] private static void UpdateReservedHotbarAfterAnimation(bool specialAnimation, PlayerControllerB __instance) { if (HUDPatcher.hasReservedItemSlotsAndEnabled && !((Object)(object)__instance != (Object)(object)localPlayerController) && !specialAnimation && !Keybinds.pressedToggleKey && ReservedPlayerData.localPlayerData.currentItemSlotIsReserved != Keybinds.holdingModifierKey) { FocusReservedHotbarSlots(Keybinds.holdingModifierKey); } } } [HarmonyPatch] public static class SessionManager { [CompilerGenerated] private sealed class <>c__DisplayClass25_0 { public bool force; } internal static List<ReservedItemSlotData> unlockedReservedItemSlots = new List<ReservedItemSlotData>(); internal static Dictionary<string, ReservedItemSlotData> unlockedReservedItemSlotsDict = new Dictionary<string, ReservedItemSlotData>(); internal static List<ReservedItemSlotData> pendingUnlockedReservedItemSlots = new List<ReservedItemSlotData>(); internal static Dictionary<string, ReservedItemSlotData> pendingUnlockedReservedItemSlotsDict = new Dictionary<string, ReservedItemSlotData>(); private static Dictionary<string, ReservedItemData> allReservedItemData = new Dictionary<string, ReservedItemData>(); internal static bool gameStarted = false; internal static List<ReservedItemSlotData> allUnlockableReservedItemSlots => SyncManager.unlockableReservedItemSlots; internal static Dictionary<string, ReservedItemSlotData> allUnlockableReservedItemSlotsDict => SyncManager.unlockableReservedItemSlotsDict; public static int numReservedItemSlotsUnlocked { get { if (unlockedReservedItemSlots == null) { return 0; } return unlockedReservedItemSlots.Count; } } [HarmonyPatch(typeof(StartOfRound), "Awake")] [HarmonyPrefix] private static void InitSession() { unlockedReservedItemSlots.Clear(); unlockedReservedItemSlotsDict.Clear(); pendingUnlockedReservedItemSlots.Clear(); pendingUnlockedReservedItemSlotsDict.Clear(); allReservedItemData.Clear(); gameStarted = false; } [HarmonyPatch(typeof(StartOfRound), "ResetPlayersLoadedValueClientRpc")] [HarmonyPostfix] private static void OnStartGame(StartOfRound __instance, bool landingShip = false) { if (gameStarted || !NetworkManager.Singleton.IsClient) { return; } if (!SyncManager.hostHasMod && SyncManager.canUseModDisabledOnHost) { Plugin.LogWarning("Starting game while host does not have this mod, and ForceEnableReservedItemSlots is enabled in the config. Unlocking: " + ReservedItemSlotData.allReservedItemSlotData.Count + " slots. THIS MAY NOT BE STABLE"); SyncManager.isSynced = true; SyncManager.enablePurchasingItemSlots = false; ReservedPlayerData.localPlayerData.reservedHotbarStartIndex = ReservedPlayerData.localPlayerData.itemSlots.Length; foreach (ReservedItemSlotData value in ReservedItemSlotData.allReservedItemSlotData.Values) { SyncManager.AddReservedItemSlotData(value); UnlockReservedItemSlot(value); } pendingUnlockedReservedItemSlots?.Clear(); pendingUnlockedReservedItemSlotsDict?.Clear(); SyncManager.UpdateReservedItemsList(); } gameStarted = true; } public static void UnlockReservedItemSlot(ReservedItemSlotData itemSlotData) { if (itemSlotData == null) { return; } Plugin.Log("Unlocking reserved item slot: " + itemSlotData.slotName); if (!SyncManager.isSynced) { if (!pendingUnlockedReservedItemSlotsDict.ContainsKey(itemSlotData.slotName)) { pendingUnlockedReservedItemSlotsDict.Add(itemSlotData.slotName, itemSlotData); pendingUnlockedReservedItemSlots.Add(itemSlotData); } return; } if (!unlockedReservedItemSlotsDict.ContainsKey(itemSlotData.slotName)) { unlockedReservedItemSlotsDict.Add(itemSlotData.slotName, itemSlotData); if (!unlockedReservedItemSlots.Contains(itemSlotData)) { int num = -1; for (int i = 0; i < unlockedReservedItemSlots.Count; i++) { if (itemSlotData.slotPriority > unlockedReservedItemSlots[i].slotPriority) { num = i; break; } } if (num == -1) { num = unlockedReservedItemSlots.Count; } for (int j = 0; j < unlockedReservedItemSlots.Count; j++) { _ = unlockedReservedItemSlots[j]; } unlockedReservedItemSlots.Insert(num, itemSlotData); foreach (ReservedPlayerData value in ReservedPlayerData.allPlayerData.Values) { if (unlockedReservedItemSlots.Count == 1) { value.reservedHotbarStartIndex = value.itemSlots.Length; } int index = value.reservedHotbarStartIndex + num; List<GrabbableObject> list = new List<GrabbableObject>(value.itemSlots); list.Insert(index, null); value.playerController.ItemSlots = list.ToArray(); value.hotbarSize = list.Count; } } } if (ReservedHotbarManager.indexInReservedHotbar < ReservedPlayerData.localPlayerData.reservedHotbarStartIndex || ReservedHotbarManager.indexInReservedHotbar >= ReservedPlayerData.localPlayerData.reservedHotbarEndIndexExcluded) { ReservedHotbarManager.indexInReservedHotbar = ReservedPlayerData.localPlayerData.reservedHotbarStartIndex; } UpdateReservedItemsList(); HUDPatcher.OnUpdateReservedItemSlots(); } internal static void UnlockAllPendingItemSlots() { foreach (ReservedItemSlotData pendingUnlockedReservedItemSlot in pendingUnlockedReservedItemSlots) { UnlockReservedItemSlot(pendingUnlockedReservedItemSlot); } pendingUnlockedReservedItemSlots.Clear(); pendingUnlockedReservedItemSlotsDict.Clear(); } public static ReservedItemSlotData GetUnlockedReservedItemSlot(int indexInUnlockedItemSlots) { if (unlockedReservedItemSlots == null || indexInUnlockedItemSlots < 0 || indexInUnlockedItemSlots >= unlockedReservedItemSlots.Count) { return null; } return unlockedReservedItemSlots[indexInUnlockedItemSlots]; } public static ReservedItemSlotData GetUnlockedReservedItemSlot(string itemSlotName) { if (TryGetUnlockedItemSlotData(itemSlotName, out var itemSlotData)) { return itemSlotData; } return null; } public static bool IsItemSlotUnlocked(ReservedItemSlotData itemSlotData) { if (itemSlotData == null) { return false; } return IsItemSlotUnlocked(itemSlotData.slotName); } public static bool IsItemSlotUnlocked(string itemSlotName) { return unlockedReservedItemSlotsDict.ContainsKey(itemSlotName); } internal static void UpdateReservedItemsList() { if (unlockedReservedItemSlots == null) { return; } allReservedItemData.Clear(); foreach (ReservedItemSlotData unlockedReservedItemSlot in unlockedReservedItemSlots) { if (unlockedReservedItemSlot.reservedItemData == null) { continue; } foreach (ReservedItemData value in unlockedReservedItemSlot.reservedItemData.Values) { if (!allReservedItemData.ContainsKey(value.itemName)) { allReservedItemData.Add(value.itemName, value); } } } } [HarmonyPatch(typeof(StartOfRound), "ResetShip")] [HarmonyPostfix] private static void OnResetShip() { if (SyncManager.enablePurchasingItemSlots) { ResetProgressDelayed(); } else if (!SyncManager.hostHasMod && SyncManager.canUseModDisabledOnHost) { SyncManager.isSynced = false; ResetProgressDelayed(force: true); } gameStarted = false; } [HarmonyPatch(typeof(GameNetworkManager), "SaveGameValues")] [HarmonyPostfix] private static void OnSaveGameValues() { if (NetworkManager.Singleton.IsHost && StartOfRound.Instance.inShipPhase && SyncManager.enablePurchasingItemSlots) { SaveGameValues(); } } [HarmonyPatch(typeof(StartOfRound), "LoadUnlockables")] [HarmonyPostfix] private static void OnLoadGameValues() { if (NetworkManager.Singleton.IsServer && SyncManager.isSynced && SyncManager.enablePurchasingItemSlots) { LoadGameValues(); } } internal static void ResetProgress(bool force = false) { if (!SyncManager.enablePurchasingItemSlots && !force) { return; } Plugin.Log("Resetting progress."); foreach (ReservedPlayerData value in ReservedPlayerData.allPlayerData.Values) { GrabbableObject[] itemSlots = value.playerController.ItemSlots; List<GrabbableObject> list = new List<GrabbableObject>(); for (int i = 0; i < itemSlots.Length; i++) { if (i < value.reservedHotbarStartIndex || i >= value.reservedHotbarEndIndexExcluded) { list.Add(itemSlots[i]); } } value.playerController.ItemSlots = list.ToArray(); } unlockedReservedItemSlots?.Clear(); unlockedReservedItemSlotsDict?.Clear(); pendingUnlockedReservedItemSlots?.Clear(); pendingUnlockedReservedItemSlotsDict?.Clear(); List<Image> list2 = new List<Image>(); List<Image> list3 = new List<Image>(); for (int j = 0; j < HUDManager.Instance.itemSlotIconFrames.Length; j++) { Image val = HUDManager.Instance.itemSlotIconFrames[j]; Image item = HUDManager.Instance.itemSlotIcons[j]; if (!HUDPatcher.reservedItemSlots.Contains(val)) { list2.Add(val); list3.Add(item); } else { Object.Destroy((Object)(object)((Component)val).gameObject); } } HUDPatcher.reservedItemSlots.Clear(); HUDManager.Instance.itemSlotIconFrames = list2.ToArray(); HUDManager.Instance.itemSlotIcons = list3.ToArray(); foreach (ReservedPlayerData value2 in ReservedPlayerData.allPlayerData.Values) { if (value2.playerController.currentItemSlot < 0 || value2.playerController.currentItemSlot >= value2.playerController.ItemSlots.Length) { PlayerPatcher.SwitchToItemSlot(value2.playerController, 0); } value2.hotbarSize = value2.itemSlots.Length; value2.reservedHotbarStartIndex = value2.hotbarSize; } foreach (ReservedItemSlotData allUnlockableReservedItemSlot in allUnlockableReservedItemSlots) { if (allUnlockableReservedItemSlot.purchasePrice <= 0) { UnlockReservedItemSlot(allUnlockableReservedItemSlot); } } _ = SyncManager.hostHasMod; HUDPatcher.OnUpdateReservedItemSlots(); if (NetworkManager.Singleton.IsServer) { ES3.DeleteKey("ReservedItemSlots.UnlockedItemSlots", GameNetworkManager.Instance.currentSaveFileName); } } internal static void ResetProgressDelayed(bool force = false) { <>c__DisplayClass25_0 CS$<>8__locals0 = new <>c__DisplayClass25_0(); CS$<>8__locals0.force = force; ((MonoBehaviour)StartOfRound.Instance).StartCoroutine(Reset()); [IteratorStateMachine(typeof(<>c__DisplayClass25_0.<<ResetProgressDelayed>g__Reset|0>d))] IEnumerator Reset() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <>c__DisplayClass25_0.<<ResetProgressDelayed>g__Reset|0>d(0) { <>4__this = CS$<>8__locals0 }; } } internal static void SaveGameValues() { if (!NetworkManager.Singleton.IsServer || unlockedReservedItemSlots == null) { return; } List<string> list = new List<string>(); foreach (ReservedItemSlotData unlockedReservedItemSlot in unlockedReservedItemSlots) { if (!list.Contains(unlockedReservedItemSlot.slotName)) { list.Add(unlockedReservedItemSlot.slotName); } } Plugin.LogWarning("Saving " + list.Count + " unlocked reserved item slots."); string[] array = list.ToArray(); ES3.Save<string[]>("ReservedItemSlots.UnlockedItemSlots", array, GameNetworkManager.Instance.currentSaveFileName); } internal static void LoadGameValues() { if (!NetworkManager.Singleton.IsServer || SyncManager.unlockableReservedItemSlotsDict == null) { return; } string[] array = ES3.Load<string[]>("ReservedItemSlots.UnlockedItemSlots", GameNetworkManager.Instance.currentSaveFileName, new string[0]); Plugin.LogWarning("Loading " + array.Length + " unlocked reserved item slots."); int num = 0; string[] array2 = array; foreach (string key in array2) { if (SyncManager.unlockableReservedItemSlotsDict.TryGetValue(key, out var value)) { num++; UnlockReservedItemSlot(value); SyncManager.SendUnlockItemSlotToClients(value.slotId); } } Plugin.Log("Loaded " + num + " unlocked reserved items."); } public static bool IsReservedItem(GrabbableObject grabbableObject) { if (!IsReservedItem(ItemNameMap.GetItemName(grabbableObject))) { if ((Object)(object)grabbableObject?.itemProperties != (Object)null) { return IsReservedItem(grabbableObject.itemProperties.itemName); } return false; } return true; } public static bool IsReservedItem(string itemName) { return allReservedItemData.ContainsKey(itemName); } public static bool TryGetUnlockedItemSlotData(string itemSlotName, out ReservedItemSlotData itemSlotData) { itemSlotData = null; unlockedReservedItemSlotsDict.TryGetValue(itemSlotName, out itemSlotData); return itemSlotData != null; } public static bool TryGetUnlockedItemData(GrabbableObject item, out ReservedItemData itemData) { itemData = null; if (!TryGetUnlockedItemData(ItemNameMap.GetItemName(item), out itemData)) { if ((Object)(object)item?.itemProperties != (Object)null) { return TryGetUnlockedItemData(item.itemProperties.itemName, out itemData); } return false; } return true; } public static bool TryGetUnlockedItemData(string itemName, out ReservedItemData itemData) { itemData = null; return allReservedItemData.TryGetValue(itemName, out itemData); } } } namespace ReservedItemSlotCore.Patches { [HarmonyPatch] internal static class DropReservedItemPatcher { [CompilerGenerated] private sealed class <>c__DisplayClass10_0 { public PlayerControllerB playerController; public float time; internal bool <SwitchToItemSlotAfterDelay>b__0() { if (!((Object)(object)playerController.currentlyHeldObjectServer == (Object)null)) { return Time.time - time >= 5f; } return true; } } [CompilerGenerated] private sealed class <SwitchToItemSlotAfterDelay>d__10 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public PlayerControllerB playerController; private <>c__DisplayClass10_0 <>8__1; public int slot; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <SwitchToItemSlotAfterDelay>d__10(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>8__1 = null; <>1__state = -2; } private bool MoveNext() { //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Expected O, but got Unknown //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>8__1 = new <>c__DisplayClass10_0(); <>8__1.playerController = playerController; <>8__1.time = Time.time; if ((Object)(object)<>8__1.playerController == (Object)(object)localPlayerController) { <>2__current = (object)new WaitUntil((Func<bool>)(() => (Object)(object)<>8__1.playerController.currentlyHeldObjectServer == (Object)null || Time.time - <>8__1.time >= 5f)); <>1__state = 1; return true; } goto IL_0091; case 1: <>1__state = -1; goto IL_0091; case 2: { <>1__state = -1; playersDiscardingItems.Remove(<>8__1.playerController); if (<>8__1.playerController.currentItemSlot != slot && Time.time - <>8__1.time < 3f && ReservedPlayerData.allPlayerData.TryGetValue(<>8__1.playerController, out var value)) { value.CallSwitchToItemSlot(slot); } return false; } IL_0091: <>2__current = (object)new WaitForEndOfFrame(); <>1__state = 2; return true; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private static HashSet<PlayerControllerB> playersDiscardingItems = new HashSet<PlayerControllerB>(); private static float timeLoggedPreventedScroll = 0f; private static PlayerControllerB localPlayerController => StartOfRound.Instance?.localPlayerController; private static bool IsNoScrapSlotName(string name) { if (string.IsNullOrEmpty(name)) { return false; } string text = name.Trim().ToLowerInvariant(); if (!(text == "no_scrap_1")) { return text == "no_scrap_2"; } return true; } [HarmonyPatch(typeof(PlayerControllerB), "SetObjectAsNoLongerHeld")] [HarmonyPatch(typeof(PlayerControllerB), "PlaceGrabbableObject")] [HarmonyPostfix] public static void OnObjectNoLongerHeld(PlayerControllerB __instance) { OnDiscardItem(__instance); } [HarmonyPatch(typeof(PlayerControllerB), "DestroyItemInSlot")] [HarmonyPostfix] public static void OnDestroyItem(int itemSlot, PlayerControllerB __instance) { if (ReservedPlayerData.localPlayerData != null && SessionManager.unlockedReservedItemSlots != null && itemSlot >= ReservedPlayerData.localPlayerData.reservedHotbarStartIndex && itemSlot < ReservedPlayerData.localPlayerData.reservedHotbarEndIndexExcluded) { if (itemSlot == __instance.currentItemSlot) { OnDiscardItem(__instance); } if ((Object)(object)__instance == (Object)(object)localPlayerController) { HUDPatcher.UpdateUI(); } } } [HarmonyPatch(typeof(PlayerControllerB), "DespawnHeldObjectOnClient")] [HarmonyPostfix] public static void OnDespawnItem(PlayerControllerB __instance) { if ((Object)(object)__instance == (Object)(object)localPlayerController) { HUDPatcher.UpdateUI(); } } [HarmonyPatch(typeof(PlayerControllerB), "DropAllHeldItems")] [HarmonyPostfix] public static void OnDropAllHeldItems(PlayerControllerB __instance) { if ((Object)(object)__instance == (Object)(object)localPlayerController) { HUDPatcher.UpdateUI(); } } private static void OnDiscardItem(PlayerControllerB playerController) { if ((Object)(object)playerController == (Object)null || playersDiscardingItems.Contains(playerController) || !ReservedPlayerData.allPlayerData.TryGetValue(playerController, out var value) || !value.currentItemSlotIsReserved || (Object)(object)value.currentlySelectedItem != (Object)null) { return; } ReservedItemSlotData currentlySelectedReservedItemSlot = value.GetCurrentlySelectedReservedItemSlot(); if (currentlySelectedReservedItemSlot != null && IsNoScrapSlotName(currentlySelectedReservedItemSlot.slotName)) { if ((Object)(object)playerController == (Object)(object)localPlayerController) { HUDPatcher.UpdateUI(); } return; } if (value.GetNumHeldReservedItems() > 0) { int num = value.CallGetNextItemSlot(forward: true); if (!value.IsReservedItemSlot(num) && !value.IsReservedItemSlot(ReservedHotbarManager.indexInHotbar)) { num = ReservedHotbarManager.indexInHotbar; } playersDiscardingItems.Add(playerController); ((MonoBehaviour)playerController).StartCoroutine(SwitchToItemSlotAfterDelay(playerController, num)); } if ((Object)(object)playerController == (Object)(object)localPlayerController) { HUDPatcher.UpdateUI(); } } [IteratorStateMachine(typeof(<SwitchToItemSlotAfterDelay>d__10))] private static IEnumerator SwitchToItemSlotAfterDelay(PlayerControllerB playerController, int slot) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <SwitchToItemSlotAfterDelay>d__10(0) { playerController = playerController, slot = slot }; } [HarmonyPatch(typeof(PlayerControllerB), "ScrollMouse_performed")] [HarmonyPrefix] public static bool PreventItemSwappingDroppingItem(CallbackContext context, PlayerControllerB __instance) { if ((Object)(object)__instance == (Object)(object)localPlayerController && playersDiscardingItems.Contains(__instance)) { float time = Time.time; if (ConfigSettings.verboseLogs.Value && time - timeLoggedPreventedScroll > 1f) { timeLoggedPreventedScroll = time; Plugin.LogWarning("[VERBOSE] Prevented item swap. Player is currently discarding an item? This should be fine, unless these logs are spamming."); } return false; } return true; } } [HarmonyPatch] public static class HUDPatcher { private static bool usingController = false; private static float itemSlotWidth; internal static float itemSlotSpacing; private static float defaultItemSlotPosX; private static float defaultItemSlotPosY; private static float defaultItemSlotSpacing; private static Vector2 defaultItemSlotSize; private static Vector2 defaultItemIconSize; private static TextMeshProUGUI hotkeyTooltip; public static List<Image> reservedItemSlots = new List<Image>(); public static HashSet<ReservedItemSlotData> toggledReservedItemSlots = new HashSet<ReservedItemSlotData>(); private static bool lerpToggledItemSlotFrames = false; private static float largestPositionDifference = 0f; private static bool currentApplyHotbarPlusSize; private static bool currentHideEmptySlots; private static readonly bool allowScroll = true; private static Image noScrap1Frame; private static Image noScrap2Frame; private static readonly HashSet<string> NoScrapSlotNames = new HashSet<string> { "no_scrap_1", "no_scrap_2" }; private static Color DefaultOutlineColor = new Color(0f, 0f, 0f, 0f); private static Color DefaultFrameColor = Color.white; private static bool DefaultColorsCaptured = false; private static bool baselineInit = false; private static float baselineCenterX = 0f; private static float baselineSpacingS = 0f; private static float baselineY = 0f; private static Vector2 baselineSize; private static readonly Color DefaultTint = new Color(0.9098039f, 0.7019608f, 1f, 1f); private static bool hasAlphaInConfig = false; private const string LocalColorPrefKey = "ReservedItemSlotCore.NonScrapSlotColor"; public static PlayerControllerB localPlayerController => StartOfRound.Instance?.localPlayerController; public static ReservedPlayerData localPlayerData => ReservedPlayerData.localPlayerData; public static bool localPlayerUsingController { get { if (!((Object)(object)StartOfRound.Instance != (Object)null)) { return false; } return StartOfRound.Instance.localPlayerUsingController; } } private static float currentItemSlotScale => itemSlotWidth / defaultItemSlotSize.x; public static bool hasReservedItemSlotsAndEnabled { get { if (reservedItemSlots != null && reservedItemSlots.Count > 0 && ((Component)reservedItemSlots[0]).gameObject.activeSelf) { return ((Behaviour)reservedItemSlots[0]).enabled; } return false; } } internal static Color Tint { get; private set; } = DefaultTint; internal static bool IsHudHidden { get; private set; } = false; internal static string EffectiveNonScrapHexUI { get; private set; } = "#E8B3FF"; internal static string EffectiveNonScrapHexSourceUI { get; private set; } = "default"; [HarmonyPatch(typeof(HUDManager), "HideHUD")] [HarmonyPostfix] private static void ReservedSlotsRespectHideHUD(bool hide) { IsHudHidden = hide; if (!hasReservedItemSlotsAndEnabled || reservedItemSlots == null) { return; } bool flag = ReservedPlayerData.localPlayerData?.currentItemSlotIsReserved ?? false; foreach (Image reservedItemSlot in reservedItemSlots) { if ((Object)(object)reservedItemSlot == (Object)null) { continue; } CanvasGroup component = ((Component)reservedItemSlot).GetComponent<CanvasGroup>(); if (!((Object)(object)component == (Object)null)) { if (hide) { component.ignoreParentGroups = false; } else { component.ignoreParentGroups = flag || ConfigSettings.preventReservedItemSlotFade.Value; } } } } private static string NormalizeHex(string s) { if (string.IsNullOrWhiteSpace(s)) { return null; } s = s.Trim(); if (!s.StartsWith("#")) { s = "#" + s; } return s.ToUpperInvariant(); } internal static void RefreshTintColor() { //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) string text = NormalizeHex(ConfigSettings.nonScrapSlotColorHex?.Value); ConfigEntry<string> nonScrapSlotColorHex = ConfigSettings.nonScrapSlotColorHex; string text2 = NormalizeHex(((nonScrapSlotColorHex == null) ? null : ((ConfigEntryBase)nonScrapSlotColorHex).DefaultValue?.ToString()) ?? "#E8B3FF"); bool flag = PlayerPrefs.HasKey("ReservedItemSlotCore.NonScrapSlotColor"); string text3 = NormalizeHex(flag ? PlayerPrefs.GetString("ReservedItemSlotCore.NonScrapSlotColor") : null); if (!string.IsNullOrEmpty(text) && !string.Equals(text, text2, StringComparison.OrdinalIgnoreCase)) { PlayerPrefs.SetString("ReservedItemSlotCore.NonScrapSlotColor", text); PlayerPrefs.Save(); text3 = text; flag = true; } string text4 = text; if (string.Equals(text, text2, StringComparison.OrdinalIgnoreCase)) { text4 = ((flag && !string.IsNullOrEmpty(text3)) ? text3 : text2); } EffectiveNonScrapHexUI = NormalizeHex((!string.IsNullOrEmpty(text4)) ? text4 : text2); Color tint = DefaultTint; hasAlphaInConfig = false; if (!string.IsNullOrEmpty(text4)) { string text5 = ((text4[0] == '#') ? text4.Substring(1) : text4); hasAlphaInConfig = text5.Length == 4 || text5.Length == 8; Color val = default(Color); if (ColorUtility.TryParseHtmlString(text4, ref val)) { tint = val; } else { hasAlphaInConfig = false; } } Tint = tint; UpdateUI(); } private static bool ShouldTint(ReservedItemSlotData slotData) { if (slotData == null) { return false; } return NoScrapSlotNames.Contains(slotData.slotName); } private static void ApplyTintToFrame(Image itemSlotFrame) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0035: 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_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0097: 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_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)itemSlotFrame == (Object)null)) { Outline obj = ((Component)itemSlotFrame).GetComponent<Outline>() ?? ((Component)itemSlotFrame).gameObject.AddComponent<Outline>(); float num = OnePixel(itemSlotFrame); ((Shadow)obj).effectDistance = new Vector2(num, 0f - num); ((Shadow)obj).effectColor = new Color(Tint.r, Tint.g, Tint.b, hasAlphaInConfig ? Tint.a : 0.1f); ((Shadow)obj).useGraphicAlpha = !hasAlphaInConfig; ((Graphic)itemSlotFrame).color = new Color(Tint.r, Tint.g, Tint.b, hasAlphaInConfig ? Tint.a : ((Graphic)itemSlotFrame).color.a); } } private static void CaptureDefaultColors(HUDManager hud) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: 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) //IL_004a: Unknown result type (might be due to invalid IL or missing references) if (DefaultColorsCaptured || (Object)(object)hud == (Object)null || hud.itemSlotIconFrames == null || hud.itemSlotIconFrames.Length == 0) { return; } Image val = hud.itemSlotIconFrames[0]; if ((Object)(object)val != (Object)null) { Outline component = ((Component)val).GetComponent<Outline>(); if ((Object)(object)component != (Object)null) { DefaultOutlineColor = ((Shadow)component).effectColor; } DefaultFrameColor = ((Graphic)val).color; DefaultColorsCaptured = true; } } private static void ResetTint(Image frame) { //IL_0045: 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_001b: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)frame == (Object)null)) { Outline component = ((Component)frame).GetComponent<Outline>(); if ((Object)(object)component != (Object)null) { ((Shadow)component).effectColor = DefaultOutlineColor; } ((Graphic)frame).color = new Color(DefaultFrameColor.r, DefaultFrameColor.g, DefaultFrameColor.b, ((Graphic)frame).color.a); } } private static float OnePixel(Image img) { Canvas val = (((Object)(object)img != (Object)null) ? ((Graphic)img).canvas : null); float num = (((Object)(object)val != (Object)null) ? val.scaleFactor : 1f); return 1f / Mathf.Max(num, 0.01f); } private static void RecenterMainHotbarWithTwoLeftReserved() { //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) HUDManager instance = HUDManager.Instance; if (!baselineInit || (Object)(object)instance == (Object)null || (Object)(object)noScrap1Frame == (Object)null || (Object)(object)noScrap2Frame == (Object)null) { return; } List<Image> list = new List<Image>(); Image[] itemSlotIconFrames = instance.itemSlotIconFrames; foreach (Image val in itemSlotIconFrames) { if (!((Object)(object)val == (Object)null) && !reservedItemSlots.Contains(val)) { list.Add(val); } } if (list.Count >= 4) { list.Sort((Image a, Image b) => ((Graphic)a).rectTransform.anchoredPosition.x.CompareTo(((Graphic)b).rectTransform.anchoredPosition.x)); float num = baselineCenterX; float num2 = baselineSpacingS; float num3 = baselineY; float[] array = new float[6]; for (int j = 0; j < 6; j++) { array[j] = num + ((float)j - 2.5f) * num2; } ((Graphic)noScrap1Frame).rectTransform.anchoredPosition = new Vector2(array[0], num3); ((Graphic)noScrap2Frame).rectTransform.anchoredPosition = new Vector2(array[1], num3); ((Graphic)list[0]).rectTransform.anchoredPosition = new Vector2(array[2], num3); ((Graphic)list[1]).rectTransform.anchoredPosition = new Vector2(array[3], num3); ((Graphic)list[2]).rectTransform.anchoredPosition = new Vector2(array[4], num3); ((Graphic)list[3]).rectTransform.anchoredPosition = new Vector2(array[5], num3); } } private static void EnsureVanillaBaseline() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: 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_002b: 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_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_011e: 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_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) HUDManager instance = HUDManager.Instance; if ((Object)(object)instance == (Object)null) { return; } Vector2 sizeDelta = ((Graphic)instance.itemSlotIconFrames[0]).rectTransform.sizeDelta; if (baselineInit && sizeDelta == baselineSize) { return; } List<Image> list = new List<Image>(); Image[] itemSlotIconFrames = instance.itemSlotIconFrames; foreach (Image val in itemSlotIconFrames) { if (!((Object)(object)val == (Object)null) && !reservedItemSlots.Contains(val)) { list.Add(val); } } if (list.Count >= 4) { list.Sort((Image a, Image b) => ((Graphic)a).rectTransform.anchoredPosition.x.CompareTo(((Graphic)b).rectTransform.anchoredPosition.x)); baselineY = ((Graphic)list[0]).rectTransform.anchoredPosition.y; float num = Mathf.Abs(((Graphic)list[1]).rectTransform.anchoredPosition.x - ((Graphic)list[0]).rectTransform.anchoredPosition.x); float num2 = Mathf.Abs(((Graphic)list[2]).rectTransform.anchoredPosition.x - ((Graphic)list[1]).rectTransform.anchoredPosition.x); float num3 = Mathf.Abs(((Graphic)list[3]).rectTransform.anchoredPosition.x - ((Graphic)list[2]).rectTransform.anchoredPosition.x); baselineSpacingS = (num + num2 + num3) / 3f; baselineCenterX = 0f; for (int j = 0; j < 4; j++) { baselineCenterX += ((Graphic)list[j]).rectTransform.anchoredPosition.x; } baselineCenterX /= 4f; baselineSize = sizeDelta; baselineInit = true; } } [HarmonyPatch(typeof(HUDManager), "Awake")] [HarmonyPostfix] public static void Initialize(HUDManager __instance) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //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_00b4: Unknown result type (might be due to invalid IL or missing references) CanvasScaler componentInParent = ((Component)__instance.itemSlotIconFrames[0]).GetComponentInParent<CanvasScaler>(); AspectRatioFitter componentInParent2 = ((Component)__instance.itemSlotIconFrames[0]).GetComponentInParent<AspectRatioFitter>(); itemSlotWidth = ((Graphic)__instance.itemSlotIconFrames[0]).rectTransform.sizeDelta.x; itemSlotSpacing = 1.125f * itemSlotWidth; defaultItemSlotPosX = componentInParent.referenceResolution.x / 2f / componentInParent2.aspectRatio - itemSlotWidth / 4f; defaultItemSlotSpacing = itemSlotSpacing; defaultItemSlotSize = ((Graphic)__instance.itemSlotIconFrames[0]).rectTransform.sizeDelta; defaultItemIconSize = ((Graphic)__instance.itemSlotIcons[0]).rectTransform.sizeDelta; defaultItemSlotPosY = ((Graphic)__instance.itemSlotIconFrames[0]).rectTransform.anchoredPosition.y; reservedItemSlots.Clear(); CaptureDefaultColors(__instance); RefreshTintColor(); } [HarmonyPatch(typeof(StartOfRound), "Update")] [HarmonyPrefix] public static void UpdateUsingController(StartOfRound __instance) { if (!((Object)(object)__instance.localPlayerController == (Object)null) && !((Object)(object)hotkeyTooltip == (Object)null) && ((Component)hotkeyTooltip).gameObject.activeSelf && ((Behaviour)hotkeyTooltip).enabled) { if (__instance.localPlayerUsingController != usingController) { usingController = __instance.localPlayerUsingController; UpdateHotkeyTooltipText(); } LerpItemSlotFrames(); } } private static void LerpItemSlotFrames() { //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: 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_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_012e: 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) if (!lerpToggledItemSlotFrames) { return; } if (largestPositionDifference < 2f && largestPositionDifference != -1f) { lerpToggledItemSlotFrames = false; } for (int i = 0; i < SessionManager.numReservedItemSlotsUnlocked; i++) { ReservedItemSlotData unlockedReservedItemSlot = SessionManager.GetUnlockedReservedItemSlot(i); if (!ShouldTint(unlockedReservedItemSlot)) { Image val = HUDManager.Instance.itemSlotIconFrames[ReservedPlayerData.localPlayerData.reservedHotbarStartIndex + i]; bool flag = unlockedReservedItemSlot.slotPriority >= 0 || !ConfigSettings.displayNegativePrioritySlotsLeftSideOfScreen.Value; Vector2 anchoredPosition = ((Graphic)val).rectTransform.anchoredPosition; anchoredPosition.x = (defaultItemSlotPosX + (defaultItemSlotSize.x - itemSlotWidth) / 2f) * (float)(flag ? 1 : (-1)); if (ReservedHotbarManager.isToggledInReservedSlots && ReservedHotbarManager.currentlyToggledItemSlots != null && ReservedHotbarManager.currentlyToggledItemSlots.Contains(unlockedReservedItemSlot)) { anchoredPosition.x += itemSlotWidth / 2f * (float)((!flag) ? 1 : (-1)); } float num = Mathf.Abs(anchoredPosition.x - ((Graphic)val).rectTransform.anchoredPosition.x); largestPositionDifference = Mathf.Max(largestPositionDifference, num); if (lerpToggledItemSlotFrames) { ((Graphic)val).rectTransform.anchoredPosition = Vector2.Lerp(((Graphic)val).rectTransform.anchoredPosition, anchoredPosition, Time.deltaTime * 10f); } else { ((Graphic)val).rectTransform.anchoredPosition = anchoredPosition; } } } } public static void OnUpdateReservedItemSlots() { //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) if (reservedItemSlots == null || SessionManager.numReservedItemSlotsUnlocked <= 0 || reservedItemSlots.Count == SessionManager.numReservedItemSlotsUnlocked) { return; } List<Image> list = new List<Image>(HUDManager.Instance.itemSlotIconFrames); List<Image> list2 = new List<Image>(HUDManager.Instance.itemSlotIcons); for (int i = reservedItemSlots.Count; i < SessionManager.numReservedItemSlotsUnlocked; i++) { Image component = Object.Instantiate<GameObject>(((Component)list[0]).gameObject, ((Component)list[0]).transform.parent).GetComponent<Image>(); Image component2 = ((Component)((Component)component).transform.GetChild(0)).GetComponent<Image>(); ((Component)component).transform.localScale = ((Component)list[0]).transform.localScale; ((Transform)((Graphic)component).rectTransform).eulerAngles = ((Transform)((Graphic)list[0]).rectTransform).eulerAngles; ((Transform)((Graphic)component2).rectTransform).eulerAngles = ((Transform)((Graphic)list2[0]).rectTransform).eulerAngles; CanvasGroup obj = ((Component)component).gameObject.AddComponent<CanvasGroup>(); obj.ignoreParentGroups = ConfigSettings.preventReservedItemSlotFade.Value; obj.alpha = 1f; component.fillMethod = list[0].fillMethod; component.sprite = list[0].sprite; ((Graphic)component).material = ((Graphic)list[0]).material; if (Plugin.IsModLoaded("xuxiaolan.hotbarrd")) { component.overrideSprite = list[0].overrideSprite; } ResetTint(component); int index = ReservedPlayerData.localPlayerData.reservedHotbarStartIndex + reservedItemSlots.Count; list.Insert(index, component); list2.Insert(index, component2); reservedItemSlots.Add(component); if (ShouldTint(SessionManager.GetUnlockedReservedItemSlot(i))) { ApplyTintToFrame(component); } } HUDManager.Instance.itemSlotIconFrames = list.ToArray(); HUDManager.Instance.itemSlotIcons = list2.ToArray(); UpdateUI(); } public static void UpdateUI() { //IL_009f: 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_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_040f: Unknown result type (might be due to invalid IL or missing references) //IL_0515: Unknown result type (might be due to invalid IL or missing references) //IL_043f: Unknown result type (might be due to invalid IL or missing references) //IL_044c: Unknown result type (might be due to invalid IL or missing references) //IL_0461: Unknown result type (might be due to invalid IL or missing references) //IL_046d: Unknown result type (might be due to invalid IL or missing references) //IL_0477: Unknown result type (might be due to invalid IL or missing references) //IL_048a: Unknown result type (might be due to invalid IL or missing references) //IL_04b2: Unknown result type (might be due to invalid IL or missing references) //IL_04e2: Unknown result type (might be due to invalid IL or missing references) //IL_0327: Unknown result type (might be due to invalid IL or missing references) if (reservedItemSlots.Count != SessionManager.numReservedItemSlotsUnlocked) { Plugin.LogError("Called UpdateUI with mismatched unlocked reserved item slots and reserved item slot hud elements."); return; } noScrap1Frame = null; noScrap2Frame = null; int num = 0; int num2 = 0; RectTransform val = null; EnsureVanillaBaseline(); Vector2 anchoredPosition = default(Vector2); for (int i = 0; i < SessionManager.numReservedItemSlotsUnlocked; i++) { ReservedItemSlotData unlockedReservedItemSlot = SessionManager.GetUnlockedReservedItemSlot(i); Array.IndexOf(HUDManager.Instance.itemSlotIconFrames, reservedItemSlots[i]); Image val2 = reservedItemSlots[i]; Image component = ((Component)((Component)reservedItemSlots[i]).transform.GetChild(0)).GetComponent<Image>(); ((Graphic)val2).rectTransform.sizeDelta = ((Graphic)HUDManager.Instance.itemSlotIconFrames[0]).rectTransform.sizeDelta; ((Graphic)component).rectTransform.sizeDelta = ((Graphic)HUDManager.Instance.itemSlotIcons[0]).rectTransform.sizeDelta; if (HotbarPlus_Compat.Enabled && !ConfigSettings.applyHotbarPlusItemSlotSize.Value) { ((Graphic)val2).rectTransform.sizeDelta = defaultItemSlotSize; ((Graphic)component).rectTransform.sizeDelta = defaultItemIconSize; } itemSlotWidth = ((Graphic)val2).rectTransform.sizeDelta.x; itemSlotSpacing = defaultItemSlotSpacing * currentItemSlotScale; if (ShouldTint(unlockedReservedItemSlot)) { float num3 = OnePixel(val2); RectTransform rectTransform = ((Graphic)val2).rectTransform; rectTransform.sizeDelta -= new Vector2(2f * num3, 2f * num3); itemSlotWidth = rectTransform.sizeDelta.x; } GrabbableObject reservedItem = ReservedPlayerData.localPlayerData.GetReservedItem(unlockedReservedItemSlot); ((Object)val2).name = "Slot" + i + " [ReservedItemSlot] (" + unlockedReservedItemSlot.slotName + ")"; ((Vector2)(ref anchoredPosition))..ctor(defaultItemSlotPosX, defaultItemSlotPosY); if (unlockedReservedItemSlot.slotPriority >= 0 || !ConfigSettings.displayNegativePrioritySlotsLeftSideOfScreen.Value) { anchoredPosition.x = defaultItemSlotPosX + (defaultItemSlotSize.x - itemSlotWidth) / 2f; anchoredPosition.y = defaultItemSlotPosY + 36f * ((itemSlotWidth / defaultItemSlotSize.x - 1f) / 2f) + itemSlotSpacing * (float)num; if (!ConfigSettings.hideEmptyReservedItemSlots.Value || (Object)(object)reservedItem != (Object)null || allowScroll) { if (!Object.op_Implicit((Object)(object)val)) { val = ((Graphic)val2).rectTransform; } num++; } else { anchoredPosition.y = -1000f; } } else { anchoredPosition.x = 0f - defaultItemSlotPosX - (defaultItemSlotSize.x - itemSlotWidth) / 2f; anchoredPosition.y = defaultItemSlotPosY + 36f * ((itemSlotWidth / defaultItemSlotSize.x - 1f) / 2f) + itemSlotSpacing * (float)num2; if (!ConfigSettings.hideEmptyReservedItemSlots.Value || (Object)(object)reservedItem != (Object)null || allowScroll) { num2++; } else { anchoredPosition.y = -1000f; } } if (!ShouldTint(unlockedReservedItemSlot)) { ((Graphic)val2).rectTransform.anchoredPosition = anchoredPosition; } else if (unlockedReservedItemSlot.slotName == "no_scrap_1") { noScrap1Frame = val2; } else if (unlockedReservedItemSlot.slotName == "no_scrap_2") { noScrap2Frame = val2; } ResetTint(val2); if (ShouldTint(unlockedReservedItemSlot)) { ApplyTintToFrame(val2); } if ((Object)(object)reservedItem != (Object)null) { ((Behaviour)component).enabled = true; component.sprite = reservedItem.itemProperties.itemIcon; } else { ((Behaviour)component).enabled = false; component.sprite = null; } } if (SessionManager.numReservedItemSlotsUnlocked > 0 && !ConfigSettings.hideFocusHotbarTooltip.Value) { if ((Object)(object)hotkeyTooltip == (Object)null) { hotkeyTooltip = new GameObject("ReservedItemSlotTooltip", new Type[2] { typeof(RectTransform), typeof(TextMeshProUGUI) }).GetComponent<TextMeshProUGUI>(); } RectTransform rectTransform2 = ((TMP_Text)hotkeyTooltip).rectTransform; ((Transform)rectTransform2).SetParent((Transform)(object)val); if (Object.op_Implicit((Object)(object)val)) { ((Transform)rectTransform2).localScale = Vector3.one; rectTransform2.sizeDelta = new Vector2(val.sizeDelta.x * 2f, 10f); rectTransform2.pivot = Vector2.one / 2f; rectTransform2.anchoredPosition3D = new Vector3(0f, 0f - rectTransform2.sizeDelta.x / 2f - itemSlotWidth / 2f - 5f, 0f); ((TMP_Text)hotkeyTooltip).font = ((TMP_Text)HUDManager.Instance.controlTipLines[0]).font; ((TMP_Text)hotkeyTooltip).fontSize = 7f * (val.sizeDelta.x / defaultItemSlotSize.x); ((TMP_Text)hotkeyTooltip).alignment = (TextAlignmentOptions)4100; UpdateHotkeyTooltipText(); } else { ((Transform)rectTransform2).localScale = Vector3.zero; } } RecenterMainHotbarWithTwoLeftReserved(); if ((Object)(object)noScrap1Frame != (Object)null) { ResetTint(noScrap1Frame); ApplyTintToFrame(noScrap1Frame); } if ((Object)(object)noScrap2Frame != (Object)null) { ResetTint(noScrap2Frame); ApplyTintToFrame(noScrap2Frame); } currentApplyHotbarPlusSize = ConfigSettings.applyHotbarPlusItemSlotSize.Value; currentHideEmptySlots = ConfigSettings.hideEmptyReservedItemSlots.Value; } public static void UpdateHotkeyTooltipText() { //IL_0091: 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_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0110: 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_00c0: 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_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)localPlayerController == (Object)null || (Object)(object)hotkeyTooltip == (Object)null || Keybinds.FocusReservedHotbarAction == null) { return; } int num = (localPlayerUsingController ? 1 : 0); string text = ""; string text2 = ""; InputBinding val; if (num >= 0 && num < Keybinds.FocusReservedHotbarAction.bindings.Count) { val = Keybinds.FocusReservedHotbarAction.bindings[num]; text = KeybindDisplayNames.GetKeybindDisplayName(((InputBinding)(ref val)).effectivePath); } else { Plugin.LogError("Failed to update FocusReservedHotbar keybind tooltip. Using controller: " + localPlayerUsingController + " NumFocusReservedHotbarActionBindings: " + Keybinds.FocusReservedHotbarAction.bindings.Count); } if (num >= 0 && num < Keybinds.ToggleFocusReservedHotbarAction.bindings.Count) { val = Keybinds.ToggleFocusReservedHotbarAction.bindings[num]; text2 = KeybindDisplayNames.GetKeybindDisplayName(((InputBinding)(ref val)).effectivePath); } else { Plugin.LogError("Failed to update ToggleFocusReservedHotbar keybind tooltip. Using controller: " + localPlayerUsingController + " NumToggleFocusReservedHotbarActionBindings: " + Keybinds.ToggleFocusReservedHotbarAction.bindings.Count); } ((TMP_Text)hotkeyTooltip).text = ""; if (allowScroll) { return; } if (text != "") { ((TMP_Text)hotkeyTooltip).text = $"Hold: [{text}]"; } if (text2 != "" && text2 != text) { if (((TMP_Text)hotkeyTooltip).text != "") { TextMeshProUGUI obj = hotkeyTooltip; ((TMP_Text)obj).text = ((TMP_Text)obj).text + "\n"; } TextMeshProUGUI obj2 = hotkeyTooltip; ((TMP_Text)obj2).text = ((TMP_Text)obj2).text + $"Toggle: [{text2}]"; } } public static void UpdateToggledReservedItemSlotsUI() { if (ReservedHotbarManager.currentlyToggledItemSlots != null) { toggledReservedItemSlots = new HashSet<ReservedItemSlotData>(ReservedHotbarManager.currentlyToggledItemSlots); } else { toggledReservedItemSlots.Clear(); } lerpToggledItemSlotFrames = true; largestPositionDifference = -1f; } private static float GetCurrentItemSlotSpacing() { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) try { Image val = HUDManager.Instance.itemSlotIconFrames[0]; Image val2 = HUDManager.Instance.itemSlotIconFrames[1]; if (((Object)val).name.ToLower().Contains("reserved") || ((Object)val2).name.ToLower().Contains("reserved")) { return defaultItemSlotSpacing; } return Mathf.Abs(((Graphic)val2).rectTransform.anchoredPosition.x - ((Graphic)val).rectTransform.anchoredPosition.x); } catch { } return defaultItemSlotSpacing; } [HarmonyPatch(typeof(QuickMenuManager), "CloseQuickMenu")] [HarmonyPostfix] public static void OnCloseQuickMenu() { if (HotbarPlus_Compat.Enabled || currentHideEmptySlots != ConfigSettings.hideEmptyReservedItemSlots.Value) { UpdateUI(); } } } [HarmonyPatch] internal class MaskedEnemyPatcher { [HarmonyPatch(typeof(MaskedPlayerEnemy), "Awake")] [HarmonyPrefix] public static void InitMaskedEnemy(MaskedPlayerEnemy __instance) { if (ConfigSettings.showReservedItemsHolsteredMaskedEnemy.Value && !MaskedEnemyData.allMaskedEnemyData.ContainsKey(__instance)) { MaskedEnemyData.allMaskedEnemyData.Add(__instance, new MaskedEnemyData(__instance)); } } [HarmonyPatch(typeof(MaskedPlayerEnemy), "OnDestroy")] [HarmonyPrefix] public static void OnDestroy(MaskedPlayerEnemy __instance) { if (MaskedEnemyData.allMaskedEnemyData.TryGetValue(__instance, out var value)) { value.DestroyEquippedItems(); MaskedEnemyData.allMaskedEnemyData.Remove(__instance); } } [HarmonyPatch(typeof(MaskedPlayerEnemy), "Update")] [HarmonyPostfix] public static void Update(MaskedPlayerEnemy __instance) { if (ConfigSettings.showReservedItemsHolsteredMaskedEnemy.Value && MaskedEnemyData.allMaskedEnemyData.TryGetValue(__instance, out var value) && (Object)(object)value.originallyMimickingPlayer == (Object)null && (Object)(object)value.maskedEnemy.mimickingPlayer != (Object)null) { AddReservedItemsToMaskedEnemy(__instance); } } public static void AddReservedItemsToMaskedEnemy(MaskedPlayerEnemy maskedEnemy) { //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) if (!ConfigSettings.showReservedItemsHolsteredMaskedEnemy.Value || !MaskedEnemyData.allMaskedEnemyData.TryGetValue(maskedEnemy, out var value)) { return; } value.originallyMimickingPlayer = value.maskedEnemy.mimickingPlayer; if (!ReservedPlayerData.allPlayerData.TryGetValue(value.originallyMimickingPlayer, out var value2)) { Plugin.LogWarning("Failed to mimic player's equipped reserved items. Could not retrieve player data from: " + value.originallyMimickingPlayer.playerUsername); return; } for (int i = value2.reservedHotbarStartIndex; i < Mathf.Min(value2.reservedHotbarEndIndexExcluded, value2.playerController.ItemSlots.Length); i++) { GrabbableObject val = value2.playerController.ItemSlots[i]; if ((Object)(object)val == (Object)null) { continue; } int num = i - value2.reservedHotbarStartIndex; if (num < 0 || num >= SessionManager.unlockedReservedItemSlots.Count) { Plugin.LogWarning("Failed to add reserved item to MaskedEnemy. Could not get ReservedItemSlot at index: " + num + " Item: " + val.itemProperties.itemName + " SlotIndexInInventory: " + i + " ReservedHotbarStartIndex: " + value2.reservedHotbarStartIndex); continue; } ReservedItemData reservedItemData = SessionManager.unlockedReservedItemSlots[num].GetReservedItemData(val); if (reservedItemData.holsteredParentBone == PlayerBone.None) { continue; } Transform bone = value.boneMap.GetBone(reservedItemData.holsteredParentBone); if ((Object)(object)bone == (Object)null) { Plugin.LogWarning("Failed to get bone from masked enemy: " + reservedItemData.holsteredParentBone); continue; } GameObject val2 = Object.Instantiate<GameObject>(((Component)val).gameObject, bone); val2.transform.localEulerAngles = reservedItemData.holsteredRotationOffset; val2.transform.localPosition = reservedItemData.holsteredPositionOffset; val2.transform.localScale = ((Component)val).transform.localScale; val2.layer = 6; MeshRenderer[] componentsInChildren = val2.GetComponentsInChildren<MeshRenderer>(); foreach (MeshRenderer val3 in componentsInChildren) { if (!((Object)val3).name.Contains("ScanNode") && !((Component)val3).gameObject.CompareTag("DoNotSet") && !((Component)val3).gameObject.CompareTag("InteractTrigger")) { ((Component)val3).gameObject.layer = 6; } } if (val is FlashlightItem) { Light[] componentsInChildren2 = val2.GetComponentsInChildren<Light>(); for (int j = 0; j < componentsInChildren2.Length; j++) { ((Behaviour)componentsInChildren2[j]).enabled = false; } } else { Light[] componentsInChildren2 = val2.GetComponentsInChildren<Light>(); for (int j = 0; j < componentsInChildren2.Length; j++) { ((Behaviour)componentsInChildren2[j]).enabled = true; } } GrabbableObject componentInChildren = val2.GetComponentInChildren<GrabbableObject>(); if ((Object)(object)componentInChildren != (Object)null) { componentInChildren.playerHeldBy = null; FlashlightItem val4 = (FlashlightItem)(object)((componentInChildren is FlashlightItem) ? componentInChildren : null); if ((Object)(object)val4 != (Object)null) { ((Behaviour)val4.flashlightBulb).enabled = true; ((Behaviour)val4.flashlightBulbGlow).enabled = true; if (((Renderer)val4.flashlightMesh).sharedMaterials.Length > 1 && (Object)(object)val4.bulbLight != (Object)null) { ((Renderer)val4.flashlightMesh).sharedMaterials[1] = val4.bulbLight; } } ReservedItemsPatcher.ForceEnableItemMesh(componentInChildren, enabled: true); componentInChildren.EnablePhysics(false); } Object.DestroyImmediate((Object)(object)val2.GetComponentInChildren<NetworkObject>()); Collider[] componentsInChildren3 = val2.GetComponentsInChildren<Collider>(); for (int j = 0; j < componentsInChildren3.Length; j++) { Object.DestroyImmediate((Object)(object)componentsInChildren3[j]); } MonoBehaviour[] componentsInChildren4 = val2.GetComponentsInChildren<MonoBehaviour>(); for (int j = 0; j < componentsInChildren4.Length; j++) { Object.DestroyImmediate((Object)(object)componentsInChildren4[j]); } } } } [HarmonyPatch] internal static class MouseScrollPatcher { private static float timeLoggedPreventedScroll; public static PlayerControllerB localPlayerController => StartOfRound.Instance?.localPlayerController; [HarmonyPatch(typeof(PlayerControllerB), "NextItemSlot")] [HarmonyPrefix] public static void CorrectReservedScrollDirectionNextItemSlot(ref bool forward) { if (Keybinds.scrollingReservedHotbar) { forward = Keybinds.RawScrollAction.ReadValue<float>() > 0f; } } [HarmonyPatch(typeof(PlayerControllerB), "SwitchItemSlotsServerRpc")] [HarmonyPrefix] public static void CorrectReservedScrollDirectionServerRpc(ref bool forward) { if (Keybinds.scrollingReservedHotbar) { forward = Keybinds.RawScrollAction.ReadValue<float>() > 0f; } } [HarmonyPatch(typeof(PlayerControllerB), "ScrollMouse_performed")] [HarmonyPrefix] public static bool PreventInvertedScrollingReservedHotbar(CallbackContext context) { if (AllowScrollCompat.LoadedAndEnabled) { return true; } if (StartOfRound.Instance.localPlayerUsingController || SessionManager.numReservedItemSlotsUnlocked <= 0 || HUDPatcher.reservedItemSlots == null || localPlayerController.inTerminalMenu) { return true; } if (ReservedPlayerData.localPlayerData.currentItemSlotIsReserved) { if (!HUDPatcher.hasReservedItemSlotsAndEnabled) { return true; } float time = Time.time; if (!Keybinds.scrollingReservedHotbar) { return false; } if (ReservedPlayerData.localPlayerData.GetNumHeldReservedItems() == 1 && (Object)(object)ReservedPlayerData.localPlayerData.currentlySelectedItem != (Object)null && !ReservedHotbarManager.isToggledInReservedSlots) { if (ConfigSettings.verboseLogs.Value && time - timeLoggedPreventedScroll > 1f) { timeLoggedPreventedScroll = time; } return false; } } return true; } } [HarmonyPatch] internal static class PlayerPatcher { [CompilerGenerated] private sealed class <>c__DisplayClass25_0 { public GrabbableObject __instance; } private static int INTERACTABLE_OBJECT_MASK = 0; public static int vanillaHotbarSize = 4; private static bool initialized = false; private static bool suppressNextAutoSwitchFromNoScrapDrop = false; private static int suppressedNoScrapSlotIndex = -1; private static int suppressExpireFrame = -1; public static PlayerControllerB localPlayerController => StartOfRound.Instance?.localPlayerController; public static Dictionary<PlayerControllerB, ReservedPlayerData> allPlayerData => ReservedPlayerData.allPlayerData; public static ReservedPlayerData localPlayerData => ReservedPlayerData.localPlayerData; public static int reservedHotbarSize => SessionManager.numReservedItemSlotsUnlocked; private static bool IsNoScrapSlotName(string name) { if (string.IsNullOrEmpty(name)) { return false; } string text = name.Trim().ToLowerInvariant(); if (!(text == "no_scrap_1")) { return text == "no_scrap_2"; } return true; } private static void ArmNoScrapDropSuppression(PlayerControllerB controller, ReservedPlayerData playerData) { if (!((Object)(object)controller == (Object)null) && playerData != null && playerData.IsReservedItemSlot(controller.currentItemSlot)) { ReservedItemSlotData currentlySelectedReservedItemSlot = playerData.GetCurrentlySelectedReservedItemSlot(); if (currentlySelectedReservedItemSlot != null && IsNoScrapSlotName(currentlySelectedReservedItemSlot.slotName)) { suppressedNoScrapSlotIndex = controller.currentItemSlot; suppressNextAutoSwitchFromNoScrapDrop = true; suppressExpireFrame = Time.frameCount + 6; Plugin.Log($"[NO_SCRAP] Armed keep-focus suppression at slot {suppressedNoScrapSlotIndex} (expires frame {suppressExpireFrame})."); } } } private static void ClearNoScrapDropSuppression() { suppressNextAutoSwitchFromNoScrapDrop = false; suppressedNoScrapSlotIndex = -1; suppressExpireFrame = -1; } [HarmonyPatch(typeof(StartOfRound), "Awake")] [HarmonyPrefix] private static void InitSession(StartOfRound __instance) { initialized = false; vanillaHotbarSize = 4; ReservedPlayerData.allPlayerData?.Clear(); ClearNoScrapDropSuppression(); } [HarmonyPatch(typeof(PlayerControllerB), "Awake")] [HarmonyPostfix] private static void InitializePlayerController(PlayerControllerB __instance) { if (!initialized) { vanillaHotbarSize = __instance.ItemSlots.Length; INTERACTABLE_OBJECT_MASK = (int)Traverse.Create((object)__instance).Field("interactableObjectsMask").GetValue(); initialized = true; } } [HarmonyPatch(typeof(PlayerControllerB), "Start")] [HarmonyPrefix] private static void InitializePlayerControllerLate(PlayerControllerB __instance) { ReservedPlayerData value = new ReservedPlayerData(__instance); if (!allPlayerData.ContainsKey(__instance)) { Plugin.Log("Initializing ReservedPlayerData for player: " + ((Object)__instance).name); allPlayerData.Add(__instance, value); } } [HarmonyPatch(typeof(PlayerControllerB), "LateUpdate")] [HarmonyPostfix] private static void CheckForChangedInventorySize(PlayerControllerB __instance) { if ((!SyncManager.isSynced && !SyncManager.canUseModDisabledOnHost) || !ReservedPlayerData.allPlayerData.TryGetValue(__instance, out var value) || reservedHotbarSize <= 0 || value.hotbarSize == __instance.ItemSlots.Length) { return; } value.hotbarSize = __instance.ItemSlots.Length; int num = -1; if ((Object)(object)__instance == (Object)(object)localPlayerController) { if (HUDPatcher.reservedItemSlots != null && HUDPatcher.reservedItemSlots.Count > 0) { num = Array.IndexOf(HUDManager.Instance.itemSlotIconFrames, HUDPatcher.reservedItemSlots[0]); Plugin.Log("OnUpdateInventorySize A for local player: " + ((Object)__instance).name + " NewReservedItemsStartIndex: " + num); } if (num == -1) { for (int i = 0; i < HUDManager.Instance.itemSlotIconFrames.Length; i++) { if (((Object)HUDManager.Instance.itemSlotIconFrames[i]).name.ToLower().Contains("reserved")) { num = i; Plugin.Log("OnUpdateInventorySize B for local player: " + ((Object)__instance).name + " NewReservedItemsStartIndex: " + num); break; } } } PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts; foreach (PlayerControllerB val in allPlayerScripts) { if (ReservedPlayerData.allPlayerData.TryGetValue(val, out var value2) && value2 != value && reservedHotbarSize > 0 && value2.hotbarSize != val.ItemSlots.Length) { value2.reservedHotbarStartIndex = num; } } } if (num == -1) { num = value.reservedHotbarStartIndex; Plugin.Log("OnUpdateInventorySize C for player: " + ((Object)__instance).name + " NewReservedItemsStartIndex: " + num); } if (num == -1) { num = vanillaHotbarSize; Plugin.Log("OnUpdateInventorySize D for player: " + ((Object)__instance).name + " NewReservedItemsStartIndex: " + num); } value.reservedHotbarStartIndex = num; if (value.reservedHotbarStartIndex < 0) { Plugin.LogError("Set new reserved start index to slot: " + value.reservedHotbarStartIndex + "."); } if (value.reservedHotbarEndIndexExcluded - 1 >= value.playerController.ItemSlots.Length) { Plugin.LogError("Set new reserved start index to slot: " + value.reservedHotbarStartIndex + " Last reserved slot index: " + (value.reservedHotbarEndIndexExcluded - 1) + " Inventory size: " + value.playerController.ItemSlots.Length + "."); } if (value.isLocalPlayer) { HUDPatcher.UpdateUI(); } } [HarmonyPatch(typeof(PlayerControllerB), "BeginGrabObject")] [HarmonyPrefix] private static bool BeginGrabReservedItemPrefix(PlayerControllerB __instance) { //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0267: Unknown result type (might be due to invalid IL or missing references) //IL_026d: Unknown result type (might be due to invalid IL or missing references) //IL_0271: Unknown result type (might be due to invalid IL or missing references) //IL_0277: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) if ((!SyncManager.isSynced && !SyncManager.canUseModDisabledOnHost) || !HUDPatcher.hasReservedItemSlotsAndEnabled) { return true; } localPlayerData.grabbingReservedItemSlotData = null; localPlayerData.grabbingReservedItemData = null; localPlayerData.grabbingReservedItem = null; localPlayerData.previousHotbarIndex = -1; if (__instance.twoHanded || __instance.sinkingValue > 0.73f) { return true; } RaycastHit val = default(RaycastHit); if (Physics.Raycast(new Ray(((Component)__instance.gameplayCamera).transform.position, ((Component)__instance.gameplayCamera).transform.forward), ref val, __instance.grabDistance, INTERACTABLE_OBJECT_MASK) && ((Component)((RaycastHit)(ref val)).collider).gameObject.layer != 8 && ((Component)((RaycastHit)(ref val)).collider).tag == "PhysicsProp") { GrabbableObject component = ((Component)((Component)((RaycastHit)(ref val)).collider).transform).gameObject.GetComponent<GrabbableObject>(); if ((Object)(object)component != (Object)null && !__instance.inSpecialInteractAnimation && !component.isHeld && !component.isPocketed) { NetworkObject networkObject = ((NetworkBehaviour)component).NetworkObject; if ((Object)(object)networkObject != (Object)null && networkObject.IsSpawned) { if (SessionManager.TryGetUnlockedItemData(component, out var itemData)) { localPlayerData.grabbingReservedItemData = itemData; localPlayerData.grabbingReservedItem = component; localPlayerData.previousHotbarIndex = Mathf.Clamp(__instance.currentItemSlot, 0, __instance.ItemSlots.Length - 1); ReservedItemSlotData firstEmptySlotForReservedItem = localPlayerData.GetFirstEmptySlotForReservedItem(itemData.itemName); if (firstEmptySlotForReservedItem != null) { localPlayerData.grabbingReservedItemSlotData = firstEmptySlotForReservedItem; Plugin.Log($"Beginning grab on reserved item: {itemData.itemName} -> slot {firstEmptySlotForReservedItem.slotName} (prev slot {localPlayerData.previousHotbarIndex})"); } else if (ItemNameMap.IsZeroValueScrap(component)) { ReservedItemSlotData firstEmptySlotForZeroValueScrap = localPlayerData.GetFirstEmptySlotForZeroValueScrap(); if (firstEmptySlotForZeroValueScrap != null) { localPlayerData.grabbingReservedItemData = new ReservedItemData("__ZERO_VALUE_SCRAP__"); localPlayerData.grabbingReservedItemSlotData = firstEmptySlotForZeroValueScrap; Plugin.Log($"Reserved full; routing IsZeroValueScrap into {firstEmptySlotForZeroValueScrap.slotName} (prev slot {localPlayerData.previousHotbarIndex})"); } } } else if (ItemNameMap.IsZeroValueScrap(component)) { ReservedItemSlotData firstEmptySlotForZeroValueScrap2 = localPlayerData.GetFirstEmptySlotForZeroValueScrap(); if (firstEmptySlotForZeroValueScrap2 != null) { localPlayerData.grabbingReservedItemData = new ReservedItemData("__ZERO_VALUE_SCRAP__"); localPlayerData.grabbingReservedItemSlotData = firstEmptySlotForZeroValueScrap2; localPlayerData.grabbingReservedItem = component; localPlayerData.previousHotbarIndex = Mathf.Clamp(__instance.currentItemSlot, 0, __instance.ItemSlots.Length - 1); Plugin.Log($"Beginning grab on zero-value scrap into slot: {firstEmptySlotForZeroValueScrap2.slotName} (prev slot {localPlayerData.previousHotbarIndex})"); } } } } } return true; } [HarmonyPatch(typeof(PlayerControllerB), "BeginGrabObject")] [HarmonyPostfix] private static void BeginGrabReservedItemPostfix(PlayerControllerB __instance) { if (localPlayerData == null || !localPlayerData.isGrabbingReservedItem || localPlayerData.IsReservedItemSlot(localPlayerData.previousHotbarIndex)) { return; } if (localPlayerData.grabbingReservedItemSlotData == null && localPlayerData.grabbingReservedItemData != null) { ReservedItemSlotData firstEmptySlotForReservedItem = localPlayerData.GetFirstEmptySlotForReservedItem(localPlayerData.grabbingReservedItemData.itemName); if (firstEmptySlotForReservedItem != null) { localPlayerData.grabbingReservedItemSlotData = firstEmptySlotForReservedItem; } } if (localPlayerData.grabbingReservedItemSlotData == null || (!localPlayerData.grabbingReservedItemSlotData.AutoSwitchOnPickup && !IsNoScrapSlotName(localPlayerData.grabbingReservedItemSlotData.slotName))) { SetSpecialGrabAnimationBool(__instance, setTrue: false, __instance.currentlyHeldObjectServer); GrabbableObject previouslyHeldItem = localPlayerData.previouslyHeldItem; if ((Object)(object)previouslyHeldItem != (Object)null) { SetSpecialGrabAnimationBool(__instance, setTrue: true, previouslyHeldItem); } __instance.playerBodyAnimator.SetBool("GrabValidated", true); __instance.playerBodyAnimator.SetBool("GrabInvalidated", false); __instance.playerBodyAnimator.ResetTrigger("SwitchHoldAnimation"); __instance.playerBodyAnimator.ResetTrigger("SwitchHoldAnimationTwoHanded"); if ((Object)(object)previouslyHeldItem != (Object)null) { __instance.playerBodyAnimator.ResetTrigger(previouslyHeldItem.itemProperties.pocketAnim); } __instance.twoHanded = (Object)(object)previouslyHeldItem != (Object)null && previouslyHeldItem.itemProperties.twoHanded; __instance.twoHandedAnimation = (Object)(object)previouslyHeldItem != (Object)null && previouslyHeldItem.itemProperties.twoHandedAnimation; } } [HarmonyPatch(typeof(PlayerControllerB), "GrabObjectClientRpc")] [HarmonyPrefix] private static void GrabReservedItemClientRpcPrefix(bool grabValidated, NetworkObjectReference grabbedObject, PlayerControllerB __instance) { //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) if ((!SyncManager.isSynced && !SyncManager.canUseModDisabledOnHost) || !NetworkHelper.IsClientExecStage((NetworkBehaviour)(object)__instance) || !ReservedPlayerData.allPlayerData.TryGetValue(__instance, out var value)) { return; } NetworkObject val = default(NetworkObject); GrabbableObject val2 = default(GrabbableObject); if ((Object)(object)NetworkManager.Singleton != (Object)null && NetworkManager.Singleton.IsListening && grabValidated && ((NetworkObjectReference)(ref grabbedObject)).TryGet(ref val, (NetworkManager)null) && ((Component)val).TryGetComponent<GrabbableObject>(ref val2)) { if (SessionManager.TryGetUnlockedItemData(val2, out var itemData)) { ReservedItemSlotData firstEmptySlotForReservedItem = value.GetFirstEmptySlotForReservedItem(itemData.itemName); if (firstEmptySlotForReservedItem != null) { value.grabbingReservedItemSlotData = firstEmptySlotForReservedItem; value.grabbingReservedItemData = itemData; value.grabbingReservedItem = val2; value.previousHotbarIndex = Mathf.Clamp(__instance.currentItemSlot, 0, __instance.ItemSlots.Length - 1); return; } if (ItemNameMap.IsZeroValueScrap(val2)) { ReservedItemSlotData firstEmptySlotForZeroValueScrap = value.GetFirstEmptySlotForZeroValueScrap(); if (firstEmptySlotForZeroValueScrap != null) { value.grabbingReservedItemSlotData = firstEmptySlotForZeroValueScrap; value.grabbingReservedItemData = new ReservedItemData("__ZERO_VALUE_SCRAP__"); value.grabbingReservedItem = val2; value.previousHotbarIndex = Mathf.Clamp(__instance.currentItemSlot, 0, __instance.ItemSlots.Length - 1); return; } } } else if (ItemNameMap.IsZeroValueScrap(val2)) { ReservedItemSlotData firstEmptySlotForZeroValueScrap2 = value.GetFirstEmptySlotForZeroValueScrap(); if (firstEmptySlotForZeroValueScrap2 != null) { value.grabbingReservedItemSlotData = firstEmptySlotForZeroValueScrap2; value.grabbingReservedItemData = new ReservedItemData("__ZERO_VALUE_SCRAP__"); value.grabbingReservedItem = val2; value.previousHotbarIndex = Mathf.Clamp(__instance.currentItemSlot, 0, __instance.ItemSlots.Length - 1); return; } } } value.grabbingReservedItemSlotData = null; value.grabbingReservedItemData = null; value.grabbingReservedItem = null; value.previousHotbarIndex = -1; } [HarmonyPatch(typeof(PlayerControllerB), "GrabObjectClientRpc")] [HarmonyPostfix] private static void GrabReservedItemClientRpcPostfix(bool grabValidated, NetworkObjectReference grabbedObject, PlayerControllerB __instance) { if ((!SyncManager.isSynced && !SyncManager.canUseModDisabledOnHost) || !NetworkHelper.IsClientExecStage((NetworkBehaviour)(object)__instance) || !ReservedPlayerData.allPlayerData.TryGetValue(__instance, out var value) || !value.isGrabbingReservedItem) { return; } if ((Object)(object)NetworkManager.Singleton != (Object)null && NetworkManager.Singleton.IsListening) { NetworkObject val = default(NetworkObject); GrabbableObject val2 = default(GrabbableObject); if (grabValidated && ((NetworkObjectReference)(ref grabbedObject)).TryGet(ref val, (NetworkManager)null) && ((Component)val).TryGetComponent<GrabbableObject>(ref val2)) { if (value.grabbingReservedItemSlotData != null) { bool flag = value.grabbingReservedItemSlotData.AutoSwitchOnPickup || IsNoScrapSlotName(value.grabbingReservedItemSlotData.slotName); if (!value.IsReservedItemSlot(value.previousHotbarIndex)) { if (!flag) { if ((Object)(object)value.previouslyHeldItem != (Object)null) { value.previouslyHeldItem.EnableItemMeshes(true); } ReservedItemsPatcher.ForceEnableItemMesh(value.grabbingReservedItem, enabled: false); Traverse.Create((object)val2).Field("previousPlayerHeldBy").SetValue((object)__instance); if (value.isLocalPlayer) { int num = value.reservedHotbarStartIndex + value.grabbingReservedItemSlotData.GetReservedItemSlotIndex(); ((Component)HUDManager.Instance.itemSlotIconFrames[num]).GetComponent<Animator>().SetBool("selectedSlot", false); ((Component)HUDManager.Instance.itemSlotIconFrames[value.previousHotbarIndex]).GetComponent<Animator>().SetBool("selectedSlot", true); ((Component)HUDManager.Instance.itemSlotIconFrames[num]).GetComponent<Animator>().Play("PanelLines", 0, 1f); ((Component)HUDManager.Instance.itemSlotIconFrames[value.previousHotbarIndex]).GetComponent<Animator>().Play("PanelEnlarge", 0, 1f); } else { SwitchToItemSlot(__instance, value.previousHotbarIndex); } SetSpecialGrabAnimationBool(__instance, setTrue: false, __instance.currentlyHeldObjectServer); GrabbableObject previouslyHeldItem = value.previouslyHeldItem; if ((Object)(object)previouslyHeldItem != (Object)null) { SetSpecialGrabAnimationBool(__instance, setTrue: true, previouslyHeldItem); } __instance.playerBodyAnimator.SetBool("GrabValidated", true); __instance.playerBodyAnimator.SetBool("GrabInvalidated", false); __instance.playerBodyAnimator.ResetTrigger("SwitchHoldAnimation"); __instance.playerBodyAnimator.ResetTrigger("SwitchHoldAnimationTwoHanded"); if ((Object)(object)previouslyHeldItem != (Object)null) { __instance.playerBodyAnimator.ResetTrigger(previouslyHeldItem.itemProperties.pocketAnim); } __instance.twoHanded = (Object)(object)previouslyHeldItem != (Object)null && previouslyHeldItem.itemProperties.twoHanded; __instance.twoHandedAnimation = (Object)(object)previouslyHeldItem != (Object)null && previouslyHeldItem.itemProperties.twoHandedAnimation; } else { int num2 = value.reservedHotbarStartIndex + val