Decompiled source of ReservedItemSlotCore v2.0.38
ReservedItemSlotCore.dll
Decompiled 2 weeks 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 LethalCompanyInputUtils.Api; using ReservedItemSlotCore.Compatibility; using ReservedItemSlotCore.Config; using ReservedItemSlotCore.Data; using ReservedItemSlotCore.Input; using ReservedItemSlotCore.Networking; using ReservedItemSlotCore.Patches; using TMPro; using TooManyEmotes; 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.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [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")] 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); return (itemName != null) ? 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 ""; } } [BepInPlugin("FlipMods.ReservedItemSlotCore", "ReservedItemSlotCore", "2.0.38")] [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_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown instance = this; CreateCustomLogger(); ConfigSettings.BindConfigSettings(); AddCustomItemSlots(); if (InputUtilsCompat.Enabled) { InputUtilsCompat.Init(); } _harmony = new Harmony("ReservedItemSlotCore"); PatchAll(); Log("ReservedItemSlotCore loaded"); } private void AddCustomItemSlots() { //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007d: 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) 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; foreach (string itemName in customItemSlotItems) { ReservedItemData itemData = new ReservedItemData(itemName); 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) { _harmony.PatchAll(item); } } private void CreateCustomLogger() { try { logger = Logger.CreateLogSource(string.Format("{0}-{1}", "ReservedItemSlotCore", "2.0.38")); } 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 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.38"; } [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(); return (ReservedPlayerData.localPlayerData.inReservedHotbarSlots && Keybinds.pressedToggleKey) || (currentlyToggledItemSlots != null && currentlySelectedReservedItemSlot != null && currentlyToggledItemSlots.Contains(currentlySelectedReservedItemSlot)); } } [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 ((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.Log("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.Log("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; } return 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 && !(localPlayerData.timeSinceSwitchingSlots < 0.3f); } 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 = true; } } } 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 { 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 => (unlockedReservedItemSlots != null) ? unlockedReservedItemSlots.Count : 0; [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; } 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) { return (unlockedReservedItemSlots != null && indexInUnlockedItemSlots >= 0 && indexInUnlockedItemSlots < unlockedReservedItemSlots.Count) ? unlockedReservedItemSlots[indexInUnlockedItemSlots] : null; } public static ReservedItemSlotData GetUnlockedReservedItemSlot(string itemSlotName) { if (TryGetUnlockedItemSlotData(itemSlotName, out var itemSlotData)) { return itemSlotData; } return null; } public static bool IsItemSlotUnlocked(ReservedItemSlotData itemSlotData) { return itemSlotData != null && 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) { ResetProgress(); } else if (!SyncManager.hostHasMod && SyncManager.canUseModDisabledOnHost) { SyncManager.isSynced = false; ResetProgress(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.reservedHotbarStartIndex = value2.itemSlots.Length; } foreach (ReservedItemSlotData allUnlockableReservedItemSlot in allUnlockableReservedItemSlots) { if (allUnlockableReservedItemSlot.purchasePrice <= 0) { UnlockReservedItemSlot(allUnlockableReservedItemSlot); } } if (SyncManager.hostHasMod) { } HUDPatcher.OnUpdateReservedItemSlots(); if (NetworkManager.Singleton.IsServer) { ES3.DeleteKey("ReservedItemSlots.UnlockedItemSlots", GameNetworkManager.Instance.currentSaveFileName); } } 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) { string itemName = ItemNameMap.GetItemName(grabbableObject); return IsReservedItem(itemName) || ((Object)(object)grabbableObject?.itemProperties != (Object)null && IsReservedItem(grabbableObject.itemProperties.itemName)); } 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; string itemName = ItemNameMap.GetItemName(item); return TryGetUnlockedItemData(itemName, out itemData) || ((Object)(object)item?.itemProperties != (Object)null && TryGetUnlockedItemData(item.itemProperties.itemName, out itemData)); } 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 { private static HashSet<PlayerControllerB> playersDiscardingItems = new HashSet<PlayerControllerB>(); private static float timeLoggedPreventedScroll = 0f; private static PlayerControllerB localPlayerController => StartOfRound.Instance?.localPlayerController; [HarmonyPatch(typeof(PlayerControllerB), "SetObjectAsNoLongerHeld")] [HarmonyPostfix] private static void OnSetObjectNoLongerHeld(bool droppedInElevator, bool droppedInShipRoom, Vector3 targetFloorPosition, GrabbableObject dropObject, PlayerControllerB __instance) { OnDiscardItem(__instance); } [HarmonyPatch(typeof(PlayerControllerB), "PlaceGrabbableObject")] [HarmonyPostfix] private static void OnPlaceGrabbableObject(Transform parentObject, Vector3 positionOffset, bool matchRotationOfParent, GrabbableObject placeObject, PlayerControllerB __instance) { OnDiscardItem(__instance); } [HarmonyPatch(typeof(PlayerControllerB), "DestroyItemInSlot")] [HarmonyPostfix] private static void OnDestroyItem(int itemSlot, PlayerControllerB __instance) { if ((Object)(object)__instance == (Object)(object)localPlayerController && itemSlot >= ReservedPlayerData.localPlayerData.reservedHotbarStartIndex && itemSlot < ReservedPlayerData.localPlayerData.reservedHotbarEndIndexExcluded) { HUDPatcher.UpdateUI(); } } [HarmonyPatch(typeof(PlayerControllerB), "DespawnHeldObjectOnClient")] [HarmonyPostfix] private static void OnDespawnItem(PlayerControllerB __instance) { if ((Object)(object)__instance == (Object)(object)localPlayerController) { HUDPatcher.UpdateUI(); } } [HarmonyPatch(typeof(PlayerControllerB), "DropAllHeldItems")] [HarmonyPostfix] private 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; } 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(); } } private static IEnumerator SwitchToItemSlotAfterDelay(PlayerControllerB playerController, int slot) { float time = Time.time; if ((Object)(object)playerController == (Object)(object)localPlayerController) { yield return (object)new WaitUntil((Func<bool>)(() => (Object)(object)playerController.currentlyHeldObjectServer == (Object)null || Time.time - time >= 5f)); } yield return (object)new WaitForEndOfFrame(); playersDiscardingItems.Remove(playerController); if (playerController.currentItemSlot != slot && Time.time - time < 3f && ReservedPlayerData.allPlayerData.TryGetValue(playerController, out var playerData)) { playerData.CallSwitchToItemSlot(slot); } } [HarmonyPatch(typeof(PlayerControllerB), "ScrollMouse_performed")] [HarmonyPrefix] private 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; public static PlayerControllerB localPlayerController => StartOfRound.Instance?.localPlayerController; public static ReservedPlayerData localPlayerData => ReservedPlayerData.localPlayerData; public static bool localPlayerUsingController => (Object)(object)StartOfRound.Instance != (Object)null && StartOfRound.Instance.localPlayerUsingController; private static float currentItemSlotScale => itemSlotWidth / defaultItemSlotSize.x; public static bool hasReservedItemSlotsAndEnabled => reservedItemSlots != null && reservedItemSlots.Count > 0 && ((Component)reservedItemSlots[0]).gameObject.activeSelf && ((Behaviour)reservedItemSlots[0]).enabled; [HarmonyPatch(typeof(HUDManager), "Awake")] [HarmonyPostfix] public static void Initialize(HUDManager __instance) { //IL_002a: 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) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: 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(); } [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_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: 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_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_0152: 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); 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_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_012f: 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++) { GameObject val = Object.Instantiate<GameObject>(((Component)list[0]).gameObject, ((Component)list[0]).transform.parent); Image component = val.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 val2 = ((Component)component).gameObject.AddComponent<CanvasGroup>(); val2.ignoreParentGroups = ConfigSettings.preventReservedItemSlotFade.Value; val2.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; } int index = ReservedPlayerData.localPlayerData.reservedHotbarStartIndex + reservedItemSlots.Count; list.Insert(index, component); list2.Insert(index, component2); reservedItemSlots.Add(component); } HUDManager.Instance.itemSlotIconFrames = list.ToArray(); HUDManager.Instance.itemSlotIcons = list2.ToArray(); UpdateUI(); } public static void UpdateUI() { //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: 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_03bd: Unknown result type (might be due to invalid IL or missing references) //IL_04d2: Unknown result type (might be due to invalid IL or missing references) //IL_03f3: Unknown result type (might be due to invalid IL or missing references) //IL_0401: Unknown result type (might be due to invalid IL or missing references) //IL_0416: Unknown result type (might be due to invalid IL or missing references) //IL_0423: Unknown result type (might be due to invalid IL or missing references) //IL_042d: Unknown result type (might be due to invalid IL or missing references) //IL_0441: Unknown result type (might be due to invalid IL or missing references) //IL_0469: Unknown result type (might be due to invalid IL or missing references) //IL_049b: Unknown result type (might be due to invalid IL or missing references) //IL_0301: 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; } int num = 0; int num2 = 0; RectTransform val = null; Vector2 anchoredPosition = default(Vector2); for (int i = 0; i < SessionManager.numReservedItemSlotsUnlocked; i++) { ReservedItemSlotData unlockedReservedItemSlot = SessionManager.GetUnlockedReservedItemSlot(i); int num3 = Array.IndexOf(HUDManager.Instance.itemSlotIconFrames, reservedItemSlots[i]); Image val2 = HUDManager.Instance.itemSlotIconFrames[ReservedPlayerData.localPlayerData.reservedHotbarStartIndex + i]; Image val3 = HUDManager.Instance.itemSlotIcons[ReservedPlayerData.localPlayerData.reservedHotbarStartIndex + i]; ((Graphic)val2).rectTransform.sizeDelta = ((Graphic)HUDManager.Instance.itemSlotIconFrames[0]).rectTransform.sizeDelta; ((Graphic)val3).rectTransform.sizeDelta = ((Graphic)HUDManager.Instance.itemSlotIcons[0]).rectTransform.sizeDelta; if (HotbarPlus_Compat.Enabled && !ConfigSettings.applyHotbarPlusItemSlotSize.Value) { ((Graphic)val2).rectTransform.sizeDelta = defaultItemSlotSize; ((Graphic)val3).rectTransform.sizeDelta = defaultItemIconSize; } itemSlotWidth = ((Graphic)val2).rectTransform.sizeDelta.x; itemSlotSpacing = defaultItemSlotSpacing * currentItemSlotScale; 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) { 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) { num2++; } else { anchoredPosition.y = -1000f; } } ((Graphic)val2).rectTransform.anchoredPosition = anchoredPosition; if ((Object)(object)reservedItem != (Object)null) { ((Behaviour)val3).enabled = true; val3.sprite = reservedItem.itemProperties.itemIcon; } else { ((Behaviour)val3).enabled = false; val3.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 rectTransform = ((TMP_Text)hotkeyTooltip).rectTransform; ((Transform)rectTransform).parent = (Transform)(object)val; if (Object.op_Implicit((Object)(object)val)) { ((Transform)rectTransform).localScale = Vector3.one; rectTransform.sizeDelta = new Vector2(val.sizeDelta.x * 2f, 10f); rectTransform.pivot = Vector2.one / 2f; rectTransform.anchoredPosition3D = new Vector3(0f, 0f - rectTransform.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)rectTransform).localScale = Vector3.zero; } } currentApplyHotbarPlusSize = ConfigSettings.applyHotbarPlusItemSlotSize.Value; currentHideEmptySlots = ConfigSettings.hideEmptyReservedItemSlots.Value; } public static void UpdateHotkeyTooltipText() { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_0070: 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_007f: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010a: 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 (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_005d: Unknown result type (might be due to invalid IL or missing references) //IL_006d: 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_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_01fe: 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; } ReservedItemSlotData reservedItemSlotData = SessionManager.unlockedReservedItemSlots[num]; ReservedItemData reservedItemData = reservedItemSlotData.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>(); foreach (Light val4 in componentsInChildren2) { ((Behaviour)val4).enabled = false; } } else { Light[] componentsInChildren3 = val2.GetComponentsInChildren<Light>(); foreach (Light val5 in componentsInChildren3) { ((Behaviour)val5).enabled = true; } } GrabbableObject componentInChildren = val2.GetComponentInChildren<GrabbableObject>(); if ((Object)(object)componentInChildren != (Object)null) { componentInChildren.playerHeldBy = null; FlashlightItem val6 = (FlashlightItem)(object)((componentInChildren is FlashlightItem) ? componentInChildren : null); if ((Object)(object)val6 != (Object)null) { ((Behaviour)val6.flashlightBulb).enabled = true; ((Behaviour)val6.flashlightBulbGlow).enabled = true; ((Renderer)val6.flashlightMesh).sharedMaterials[1] = val6.bulbLight; } ReservedItemsPatcher.ForceEnableItemMesh(componentInChildren, enabled: true); componentInChildren.EnablePhysics(false); } Object.DestroyImmediate((Object)(object)val2.GetComponentInChildren<NetworkObject>()); Collider[] componentsInChildren4 = val2.GetComponentsInChildren<Collider>(); foreach (Collider val7 in componentsInChildren4) { Object.DestroyImmediate((Object)(object)val7); } MonoBehaviour[] componentsInChildren5 = val2.GetComponentsInChildren<MonoBehaviour>(); foreach (MonoBehaviour val8 in componentsInChildren5) { Object.DestroyImmediate((Object)(object)val8); } } } } [HarmonyPatch] internal static class MouseScrollPatcher { private static bool scrollingItemSlots; 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 (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(typeof(PlayerControllerB), "ScrollMouse_performed")] [HarmonyPostfix] public static void ScrollReservedItemSlots(CallbackContext context) { scrollingItemSlots = false; } } [HarmonyPatch] internal static class PlayerPatcher { private static int INTERACTABLE_OBJECT_MASK = 0; public static int vanillaHotbarSize = 4; private static bool initialized = false; 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; [HarmonyPatch(typeof(StartOfRound), "Awake")] [HarmonyPrefix] private static void InitSession(StartOfRound __instance) { initialized = false; vanillaHotbarSize = 4; ReservedPlayerData.allPlayerData?.Clear(); } [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 + ". Maybe share these logs with Flip? :)"); } 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 + ". Maybe share these logs with Flip? :)"); } if (value.isLocalPlayer) { HUDPatcher.UpdateUI(); } } [HarmonyPatch(typeof(PlayerControllerB), "BeginGrabObject")] [HarmonyPrefix] private static bool BeginGrabReservedItemPrefix(PlayerControllerB __instance) { //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0093: 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) 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; } Ray val = default(Ray); ((Ray)(ref val))..ctor(((Component)__instance.gameplayCamera).transform.position, ((Component)__instance.gameplayCamera).transform.forward); RaycastHit val2 = default(RaycastHit); if (Physics.Raycast(val, ref val2, __instance.grabDistance, INTERACTABLE_OBJECT_MASK) && ((Component)((RaycastHit)(ref val2)).collider).gameObject.layer != 8 && ((Component)((RaycastHit)(ref val2)).collider).tag == "PhysicsProp") { GrabbableObject component = ((Component)((Component)((RaycastHit)(ref val2)).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 && SessionManager.TryGetUnlockedItemData(component, out var itemData)) { localPlayerData.grabbingReservedItemData = itemData; localPlayerData.grabbingReservedItem = component; localPlayerData.previousHotbarIndex = Mathf.Clamp(__instance.currentItemSlot, 0, __instance.ItemSlots.Length - 1); Plugin.Log("Beginning grab on reserved item: " + itemData.itemName + " Previous item 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)) { SetSpecialGrabAnimationBool(__instance, setTrue: false); SetSpecialGrabAnimationBool(__instance, (Object)(object)localPlayerData.previouslyHeldItem != (Object)null, localPlayerData.previouslyHeldItem); __instance.playerBodyAnimator.SetBool("GrabValidated", true); __instance.playerBodyAnimator.SetBool("GrabInvalidated", false); __instance.playerBodyAnimator.ResetTrigger("SwitchHoldAnimation"); __instance.playerBodyAnimator.ResetTrigger("SwitchHoldAnimationTwoHanded"); if ((Object)(object)localPlayerData.previouslyHeldItem != (Object)null) { __instance.playerBodyAnimator.ResetTrigger(localPlayerData.previouslyHeldItem.itemProperties.pocketAnim); } __instance.twoHanded = (Object)(object)localPlayerData.previouslyHeldItem != (Object)null && localPlayerData.previouslyHeldItem.itemProperties.twoHanded; __instance.twoHandedAnimation = (Object)(object)localPlayerData.previouslyHeldItem != (Object)null && localPlayerData.previouslyHeldItem.itemProperties.twoHandedAnimation; } } [HarmonyPatch(typeof(PlayerControllerB), "GrabObjectClientRpc")] [HarmonyPrefix] private static void GrabReservedItemClientRpcPrefix(bool grabValidated, NetworkObjectReference grabbedObject, PlayerControllerB __instance) { 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) && 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; } } 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 (SessionManager.TryGetUnlockedItemData(val2, out var itemData)) { if (!value.IsReservedItemSlot(value.previousHotbarIndex)) { 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); if (itemData.showOnPlayerWhileHolstered) { val2.EnableItemMeshes(true); } } SetSpecialGrabAnimationBool(__instance, setTrue: false); SetSpecialGrabAnimationBool(__instance, (Object)(object)value.previouslyHeldItem != (Object)null, value.previouslyHeldItem); __instance.playerBodyAnimator.SetBool("GrabValidated", true); __instance.playerBodyAnimator.SetBool("GrabInvalidated", false); __instance.playerBodyAnimator.ResetTrigger("SwitchHoldAnimation"); __instance.playerBodyAnimator.ResetTrigger("SwitchHoldAnimationTwoHanded"); if ((Object)(object)value.previouslyHeldItem != (Object)null) { __instance.playerBodyAnimator.ResetTrigger(value.previouslyHeldItem.itemProperties.pocketAnim); } __instance.twoHanded = (Object)(object)value.previouslyHeldItem != (Object)null && value.previouslyHeldItem.itemProperties.twoHanded; __instance.twoHandedAnimation = (Object)(object)value.previouslyHeldItem != (Object)null && value.previouslyHeldItem.itemProperties.twoHandedAnimation; } if (value.isLocalPlayer) { HUDPatcher.UpdateUI(); return; } value.grabbingReservedItemSlotData = null; value.grabbingReservedItemData = null; value.grabbingReservedItem = null; value.previousHotbarIndex = -1; return; } } else if (value.isLocalPlayer) { Plugin.LogWarning("Failed to validate ReservedItemGrab by the local player. Object id: " + ((NetworkObjectReference)(ref grabbedObject)).NetworkObjectId + ". Internal error?"); Traverse.Create((object)localPlayerController).Field("grabInvalidated").SetValue((object)true); } else { Plugin.LogWarning("Failed to validate ReservedItemGrab by player with id: " + ((Object)__instance).name + ". Object id: " + ((NetworkObjectReference)(ref grabbedObject)).NetworkObjectId + ". Internal error?"); } } value.grabbingReservedItemSlotData = null; value.grabbingReservedItemData = null; value.grabbingReservedItem = null; value.previousHotbarIndex = -1; } [HarmonyPatch(typeof(GrabbableObject), "GrabItemOnClient")] [HarmonyPrefix] private static void OnReservedItemGrabbed(GrabbableObject __instance) { if (localPlayerData.grabbingReservedItemData != null && (Object)(object)__instance == (Object)(object)GetCurrentlyGrabbingObject(localPlayerController)) { ((MonoBehaviour)localPlayerController).StartCoroutine(OnReservedItemGrabbedEndOfFrame()); } IEnumerator OnReservedItemGrabbedEndOfFrame() { yield return (object)new WaitForEndOfFrame(); if (localPlayerData.isGrabbingReservedItem) { if (localPlayerData.previousHotbarIndex < 0 || localPlayerData.previousHotbarIndex >= localPlayerController.ItemSlots.Length || localPlayerData.IsReservedItemSlot(localPlayerData.previousHotbarIndex)) { localPlayerData.previousHotbarIndex = 0; } SwitchToItemSlot(localPlayerController, localPlayerData.previousHotbarIndex); GrabbableObject obj = __instance; if (obj != null) { obj.PocketItem(); } SetSpecialGrabAnimationBool(localPlayerController, setTrue: false); SetSpecialGrabAnimationBool(localPlayerController, (Object)(object)localPlayerData.previouslyHeldItem != (Object)null, localPlayerData.previouslyHeldItem); localPlayerController.playerBodyAnimator.SetBool("GrabValidated", true); localPlayerController.playerBodyAnimator.SetBool("GrabInvalidated", false); localPlayerController.playerBodyAnimator.ResetTrigger("SwitchHoldAnimation"); localPlayerController.isGrabbingObjectAnimation = false; localPlayerController.playerBodyAnimator.ResetTrigger("SwitchHoldAnimationTwoHanded"); if ((Object)(object)localPlayerData.previouslyHeldItem != (Object)null) { localPlayerController.playerBodyAnimator.ResetTrigger(localPlayerData.previouslyHeldItem.itemProperties.pocketAnim); } localPlayerController.twoHanded = (Object)(object)localPlayerData.previouslyHeldItem != (Object)null && localPlayerData.previouslyHeldItem.itemProperties.twoHanded; localPlayerController.twoHandedAnimation = (Object)(object)localPlayerData.previouslyHeldItem != (Object)null && localPlayerData.previouslyHeldItem.itemProperties.twoHandedAnimation; } localPlayerData.grabbingReservedItemSlotData = null; localPlayerData.grabbingReservedItemData = null; localPlayerData.grabbingReservedItem = null; localPlayerData.previousHotbarIndex = -1; } } [HarmonyPatch(typeof(PlayerControllerB), "SwitchToItemSlot")] [HarmonyPrefix] private static void UpdateLastSelectedHotbarIndex(int slot, PlayerControllerB __instance) { int currentItemSlot = __instance.currentItemSlot; if (ReservedPlayerData.allPlayerData.TryGetValue(__instance, out var value)) { if (value.IsReservedItemSlot(currentItemSlot)) { ReservedHotbarManager.indexInReservedHotbar = currentItemSlot; } else { ReservedHotbarManager.indexInHotbar = currentItemSlot; } } } [HarmonyPatch(typeof(PlayerControllerB), "SwitchToItemSlot")] [HarmonyPostfix] private static void UpdateFocusReservedHotbar(int slot, PlayerControllerB __instance) { if (HUDPatcher.hasReservedItemSlotsAndEnabled && ReservedPlayerData.allPlayerData.TryGetValue(__instance, out var value)) { bool inReservedHotbarSlots = value.inReservedHotbarSlots; value.inReservedHotbarSlots = value.IsReservedItemSlot(__instance.currentItemSlot); bool flag = false; if (inReservedHotbarSlots != value.inReservedHotbarSlots || (value.inReservedHotbarSlots && ReservedHotbarManager.isToggledInReservedSlots && ReservedHotbarManager.currentlyToggledItemSlots != null && !ReservedHotbarManager.currentlyToggledItemSlots.Contains(value.GetCurrentlySelectedReservedItemSlot()))) { flag = true; } if (value.inReservedHotbarSlots) { ReservedHotbarManager.OnSwapToReservedHotbar(); } else { ReservedHotbarManager.OnSwapToVanillaHotbar(); } if (flag) { HUDPatcher.UpdateToggledReservedItemSlotsUI(); } } } [HarmonyPatch(typeof(PlayerControllerB), "FirstEmptyItemSlot")] [HarmonyPostfix] private static void GetReservedItemSlotPlacementIndex(ref int __result, PlayerControllerB __instance) { if (reservedHotbarSize <= 0 || !HUDPatcher.hasReservedItemSlotsAndEnabled || !ReservedPlayerData.allPlayerData.TryGetValue(__instance, out var value)) { return; } ReservedItemData grabbingReservedItemData = value.grabbingReservedItemData; if (grabbingReservedItemData != null) { ReservedItemSlotData firstEmptySlotForReservedItem = value.GetFirstEmptySlotForReservedItem(grabbingReservedItemData.itemName); if (firstEmptySlotForReservedItem != null) { __result = firstEmptySlotForReservedItem.GetIndexInInventory(__instance); return; } value.grabbingReservedItemSlotData = null; value.grabbingReservedItemData = null; value.grabbingReservedItem = null; value.previousHotbarIndex = -1; } if (!value.IsReservedItemSlot(__result)) { return; } __result = -1; for (int i = 0; i < __instance.ItemSlots.Length; i++) { if (!value.IsReservedItemSlot(i) && (Object)(object)__instance.ItemSlots[i] == (Object)null) { __result = i; break; } } } [HarmonyPatch(typeof(PlayerControllerB), "NextItemSlot")] [HarmonyPostfix] private static void OnNextItemSlot(ref int __result, bool forward, PlayerControllerB __instance) { if (reservedHotbarSize <= 0 || !HUDPatcher.hasReservedItemSlotsAndEnabled || !ReservedPlayerData.allPlayerData.TryGetValue(__instance, out var value)) { return; } bool inReservedHotbarSlots = value.inReservedHotbarSlots; bool flag = value.IsReservedItemSlot(__result); bool flag2 = inReservedHotbarSlots; if (inReservedHotbarSlots) { ReservedItemSlotData unlockedReservedItemSlot = SessionManager.GetUnlockedReservedItemSlot(__result - value.reservedHotbarStartIndex); if (ReservedHotbarManager.isToggledInReservedSlots && !Keybinds.pressedToggleKey && !Keybinds.holdingModifierKey && ReservedHotbarManager.currentlyToggledItemSlots != null && (!flag || (Object)(object)value.itemSlots[__result] == (Object)null || !ReservedHotbarManager.currentlyToggledItemSlots.Contains(unlockedReservedItemSlot))) { __result = ReservedHotbarManager.indexInHotbar; return; } } if (flag == flag2 && (!flag || (Object)(object)__instance.ItemSlots[__result] != (Object)null)) { return; } int num = (forward ? 1 : (-1)); __result = __instance.currentItemSlot + num; __result = ((__result < 0) ? (__instance.ItemSlots.Length - 1) : ((__result < __instance.ItemSlots.Length) ? __result : 0)); flag = value.IsReservedItemSlot(__result); if (!flag2) { if (flag) { __result = (forward ? ((value.reservedHotbarStartIndex + reservedHotbarSize) % __instance.ItemSlots.Length) : (value.reservedHotbarStartIndex - 1)); } return; } __result = (flag ? __result : (forward ? value.reservedHotbarStartIndex : (value.reservedHotbarStartIndex + reservedHotbarSize - 1))); int numHeldReservedItems = value.GetNumHeldReservedItems(); while (numHeldReservedItems > 0 && __result != value.currentItemSlot && (Object)(object)__instance.ItemSlots[__result] == (Object)null) { __result += num; __result = ((!value.IsReservedItemSlot(__result)) ? (forward ? value.reservedHotbarStartIndex : (value.reservedHotbarStartIndex + reservedHotbarSize - 1)) : __result); } } [HarmonyPatch(typeof(HUDManager), "ClearControlTips")] [HarmonyPrefix] private static bool PreventClearControlTipsGrabbingReservedItem(HUDManager __instance) { return ReservedPlayerData.localPlayerData == null || (Object)(object)ReservedPlayerData.localPlayerData.grabbingReservedItem == (Object)null; } [HarmonyPatch(typeof(GrabbableObject), "SetControlTipsForItem")] [HarmonyPrefix] private static bool PreventUpdateControlTipsGrabbingReservedItem(GrabbableObject __instance) { return ReservedPlayerData.localPlayerData == null || (Object)(object)ReservedPlayerData.localPlayerData.grabbingReservedItem != (Object)(object)__instance; } private static GrabbableObject GetCurrentlyGrabbingObject(PlayerControllerB playerController) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown return (GrabbableObject)Traverse.Create((object)playerController).Field("currentlyGrabbingObject").GetValue(); } private static void SetCurrentlyGrabbingObject(PlayerControllerB playerController, GrabbableObject grabbable) { Traverse.Create((object)playerController).Field("currentlyGrabbingObject").SetValue((object)grabbable); } public static bool ReservedItemIsBeingGrabbed(GrabbableObject grabbableObject) { if ((Object)(object)grabbableObject == (Object)null) { return false; } foreach (ReservedPlayerData value in ReservedPlayerData.allPlayerData.Values) { if ((Object)(object)grabbableObject == (Object)(object)value.grabbingReservedItem) { return true; } } return false; } public static void SetSpecialGrabAnimationBool(PlayerControllerB playerController, bool setTrue, GrabbableObject currentItem = null) { MethodInfo method = ((object)playerController).GetType().GetMethod("SetSpecialGrabAnimationBool", BindingFlags.Instance | BindingFlags.NonPublic); method.Invoke(playerController, new object[2] { setTrue, currentItem }); } public static void SwitchToItemSlot(PlayerControllerB playerController, int slot, GrabbableObject fillSlotWithItem = null) { MethodInfo method = ((object)playerController).GetType().GetMethod("SwitchToItemSlot", BindingFlags.Instance | BindingFlags.NonPublic); method.Invoke(playerController, new object[2] { slot, fillSlotWithItem }); if (ReservedPlayerData.allPlayerData.TryGetValue(playerController, out var value)) { value.timeSinceSwitchingSlots = 0f; } } } [HarmonyPatch] internal static class ReservedItemsPatcher { public static bool ignoreMeshOverride; public static PlayerControllerB localPlayerController => StartOfRound.Instance?.localPlayerController; [HarmonyPatch(typeof(GrabbableObject), "PocketItem")] [HarmonyPostfix] private static void OnPocketReservedItem(GrabbableObject __instance) { if (!ConfigSettings.showReservedItemsHolstered.Value || (Object)(object)__instance.playerHeldBy == (Object)null || !ReservedPlayerData.allPlayerData.TryGetValue(__instance.playerHeldBy, out var value) || !SessionManager.TryGetUnlockedItemData(__instance, out var itemData) || !value.IsItemInReservedItemSlot(__instance) || !itemData.showOnPlayerWhileHolstered) { return; } MeshRenderer[] componentsInChildren = ((Component)__instance).GetComponentsInChildren<MeshRenderer>(); foreach (MeshRenderer val in componentsInChildren) { if (!((Component)val).gameObject.CompareTag("DoNotSet") && !((Component)val).gameObject.CompareTag("InteractTrigger") && ((Component)val).gameObject.layer != 14 && ((Component)val).gameObject.layer != 22) { ((Component)val).gameObject.layer = (value.isLocalPlayer ? 23 : 6); } } __instance.parentObject = value.boneMap.GetBone(itemData.holsteredParentBone); ForceEnableItemMesh(__instance, enabled: true); } [HarmonyPatch(typeof(GrabbableObject), "EquipItem")] [HarmonyPostfix] private static void OnEquipReservedItem(GrabbableObject __instance) { if (!ConfigSettings.showReservedItemsHolstered.Value || (Object)(object)__instance.playerHeldBy == (Object)null || !ReservedPlayerData.allPlayerData.TryGetValue(__instance.playerHeldBy, out var value) || !SessionManager.TryGetUnlockedItemData(__instance, out var itemData) || !value.IsItemInReservedItemSlot(__instance) || !itemData.showOnPlayerWhileHolstered) { return; } MeshRenderer[] componentsInChildren = ((Component)__instance).GetComponentsInChildren<MeshRenderer>(); foreach (MeshRenderer val in componentsInChildren) { if (!((Component)val).gameObject.CompareTag("DoNotSet") && !((Component)val).gameObject.CompareTag("InteractTrigger") && ((Component)val).gameObject.layer != 14 && ((Component)val).gameObject.layer != 22) { ((Component)val).gameObject.layer = 6; } } __instance.parentObject = (value.isLocalPlayer ? __instance.playerHeldBy.localItemHolder : __instance.playerHeldBy.serverItemHolder); } [HarmonyPatch(typeof(GrabbableObject), "DiscardItem")] [HarmonyPostfix] private static void ResetReservedItemLayer(GrabbableObject __instance) { if (!SessionManager.TryGetUnlockedItemData(__instance, out var itemData) || !itemData.showOnPlayerWhileHolstered) { return; } MeshRenderer[] componentsInChildren = ((Component)__instance).GetComponentsInChildren<MeshRenderer>(); foreach (MeshRenderer val in componentsInChildren) { if (!((Component)val).gameObject.CompareTag("DoNotSet") && !((Component)val).gameObject.CompareTag("InteractTrigger") && ((Component)val).gameObject.layer != 14 && ((Component)val).gameObject.layer != 22) { ((Component)val).gameObject.layer = 6; } } } [HarmonyPatch(typeof(GrabbableObject), "LateUpdate")] [HarmonyPostfix] private static void SetHolsteredPositionRotation(GrabbableObject __instance) { //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: 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_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: 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) if (ConfigSettings.showReservedItemsHolstered.Value && !((Object)(object)__instance.playerHeldBy == (Object)null) && !((Object)(object)__instance.parentObject == (Object)null) && ReservedPlayerData.allPlayerData.TryGetValue(__instance.playerHeldBy, out var value) && SessionManager.TryGetUnlockedItemData(__instance, out var itemData) && value.IsItemInReservedItemSlot(__instance) && itemData.showOnPlayerWhileHolstered && (Object)(object)__instance != (Object)(object)value.currentlySelectedItem) { Transform transform = ((Component)__instance.parentObject).transform; ((Component)__instance).transform.rotation = ((Component)__instance.parentObject).transform.rotation * Quaternion.Euler(itemData.holsteredRotationOffset); ((Component)__instance).transform.position = transform.position + transform.rotation * itemData.holsteredPositionOffset; } } [HarmonyPatch(typeof(GrabbableObject), "EnableItemMeshes")] [HarmonyPrefix] private static void OnEnableItemMeshes(ref bool enable, GrabbableObject __instance) { if (ConfigSettings.showReservedItemsHolstered.Value) { if ((Object)(object)__instance.playerHeldBy != (Object)null && !ignoreMeshOverride && ReservedPlayerData.allPlayerData.TryGetValue(__instance.playerHeldBy, out var value) && SessionManager.TryGetUnlockedItemData(__instance, out var itemData) && value.IsItemInReservedItemSlot(__instance) && itemData.showOnPlayerWhileHolstered && (Object)(object)value.currentlySelectedItem != (Object)(object)__instance && !PlayerPatcher.ReservedItemIsBeingGrabbed(__instance)) { enable = true; } ignoreMeshOverride = false; } } public static void ForceEnableItemMesh(GrabbableObject grabbableObject, bool enabled) { ignoreMeshOverride = true; grabbableObject.EnableItemMeshes(enabled); } } [HarmonyPatch] internal static class SyncAlreadyHeldObjectsPatcher { [HarmonyPatch(typeof(StartOfRound), "SyncAlreadyHeldObjectsClientRpc")] [HarmonyPrefix] private static bool SyncAlreadyHeldReservedObjectsClientRpc(ref NetworkObjectReference[] gObjects, ref int[] playersHeldBy, ref int[] itemSlotNumbers, ref int[] isObjectPocketed, int syncWithClient, StartOfRound __instance) { if ((Object)(object)NetworkManager.Singleton == (Object)null || !NetworkManager.Singleton.IsListening) { return true; } if ((NetworkHelper.IsClientExecStage((NetworkBehaviour)(object)__instance) || (!NetworkManager.Singleton.IsServer && !NetworkManager.Singleton.IsHost)) && (!NetworkHelper.IsClientExecStage((NetworkBehaviour)(object)__instance) || (!NetworkManager.Singleton.IsClient && !NetworkManager.Singleton.IsHost) || syncWithClient != (int)NetworkManager.Singleton.LocalClientId)) { return false; } bool flag = false; List<NetworkObjectReference> list = new List<NetworkObjectReference>(gObjects); List<int> list2 = new List<int>(playersHeldBy); List<int> list3 = new List<int>(itemSlotNumbers); List<int> list4 = new List<int>(isObjectPocketed); for (int num = itemSlotNumbers.Length - 1; num >= 0; num--) { if (itemSlotNumbers[num] >= __instance.localPlayerController.ItemSlots.Length) { list.RemoveAt(num); list2.RemoveAt(num); list3.RemoveAt(num); list4.Remove(num); flag = true; } } if (flag) { gObjects = list.ToArray(); playersHeldBy = list2.ToArray(); itemSlotNumbers = list3.ToArray(); isObjectPocketed = list4.ToArray(); } return true; } } [HarmonyPatch] internal static class TerminalPatcher { public static Terminal terminalInstance; public static bool initializedTerminalNodes; public static ReservedItemSlotData purchasingItemSlot; [HarmonyPatch(typeof(Terminal), "Awake")] [HarmonyPrefix] public static void InitializeTerminal(Terminal __instance) { terminalInstance = __instance; initializedTerminalNodes = false; EditExistingTerminalNodes(); } [HarmonyPatch(typeof(Terminal), "BeginUsingTerminal")] [HarmonyPrefix] public static void OnBeginUsingTerminal(Terminal __instance) { if (!initializedTerminalNodes && SyncManager.isSynced) { EditExistingTerminalNodes(); } } public static void EditExistingTerminalNodes() { if (!SyncManager.isSynced) { return; } initializedTerminalNodes = true; if (!SyncManager.enablePurchasingItemSlots) { return; } foreach (TerminalNode specialNode in terminalInstance.terminalNodes.specialNodes) { if (((Object)specialNode).name == "Start" && !specialNode.displayText.Contains("[ReservedItemSlots]")) { string text = "Type \"Help\" for a list of commands."; int num = specialNode.displayText.IndexOf(text); if (num != -1) { num += text.Length; string value = "\n\n[ReservedItemSlots]\nType \"Reserved\" to purchase reserved item slots."; specialNode.displayText = specialNode.displayText.Insert(num, value); } else { Plugin.LogError("Failed to add reserved item slots tip to terminal. Maybe an update broke it?"); } } else if (((Object)specialNode).name == "HelpCommands" && !specialNode.displayText.Contains(">RESERVED")) { string value2 = "[numberOfItemsOnRoute]"; int num2 = specialNode.displayText.IndexOf(value2); if (num2 != -1) { string text2 = ">RESERVED\n"; text2 += "Purchase reserved item slots.\n\n"; specialNode.displayText = specialNode.displayText.Insert(num2, text2); } } } } [HarmonyPatch(typeof(Terminal), "TextPostProcess")] [HarmonyPrefix] public static void TextPostProcess(ref string modifiedDisplayText, TerminalNode node) { if (modifiedDisplayText.Length <= 0) { return; } string text = "[[[reservedItemSlotsSelectionList]]]"; if (!modifiedDisplayText.Contains(text)) { return; } int num = modifiedDisplayText.IndexOf(text); int num2 = num + text.Length; string oldValue = modifiedDisplayText.Substring(num, num2 - num); string text2 = ""; if (!SyncManager.enablePurchasingItemSlots) { text2 += "Every reserved item slot is unlocked!\n\n"; } else { text2 += "Reserved Item Slots\n------------------------------\n\n"; text2 += "To purchase a reserved item slot, type the following command.\n> RESERVED [item_slot]\n\n"; int num3 = 0; foreach (ReservedItemSlotData value in SyncManager.unlockableReservedItemSlotsDict.Values) { num3 = Mathf.Max(num3, value.slotName.Length); } foreach (ReservedItemSlotData value2 in SyncManager.unlockableReservedItemSlotsDict.Values) { string arg = (SessionManager.IsItemSlotUnlocked(value2) ? "[Purchased]" : ("$" + value2.purchasePrice)); text2 += $"* {value2.slotDisplayName}{new string(' ', num3 - value2.slotDisplayName.Length)} // {arg}\n"; } } modifiedDisplayText = modifiedDisplayText.Replace(oldValue, text2); } [HarmonyPatch(typeof(Terminal), "ParsePlayerSentence")] [HarmonyPrefix] public static bool ParsePlayerSentence(ref TerminalNode __result, Terminal __instance) { if (__instance.screenText.text.Length <= 0) { return true; } string text = __instance.screenText.text.Substring(__instance.screenText.text.Length - __instance.textAdded).ToLower(); string[] array = text.Split(new char[1] { ' ' }); ReservedItemSlotData reservedItemSlotData = null; if (!SyncManager.isSynced) { if (text.StartsWith("reserved")) { __result = BuildTerminalNodeHostDoesNotHaveMod(); return false; } return true; } if (purchasingItemSlot != null) { if ("confirm".StartsWith(text)) { if (purchasingItemSlot.isUnlocked) { Plugin.LogWarning("Attempted to confirm purchase on reserved item slot that was already unlocked. Item slot: " + purchasingItemSlot.slotDisplayName); __result = BuildTerminalNodeAlreadyUnlocked(purchasingItemSlot); } else if (terminalInstance.groupCredits < purchasingItemSlot.purchasePrice) { Plugin.LogWarning("Attempted to confirm purchase with insufficient credits. Current credits: " + terminalInstance.groupCredits + " Required credits: " + purchasingItemSlot.purchasePrice); __result = BuildTerminalNodeInsufficientFunds(purchasingItemSlot); } else { Plugin.Log("Purchasing reserved item slot: " + purchasingItemSlot.slotDisplayName + ". Price: " + purchasingItemSlot.purchasePrice); Terminal obj = terminalInstance; obj.groupCredits -= purchasingItemSlot.purchasePrice; terminalInstance.BuyItemsServerRpc(new int[0], terminalInstance.groupCredits, terminalInstance.numberOfItemsInDropship); SyncManager.SendUnlockItemSlotUpdateToServer(purchasingItemSlot.slotId); __result = BuildTerminalNodeOnPurchased(purchasingItemSlot, terminalInstance.groupCredits); } } else { Plugin.Log("Canceling order."); __result = BuildCustomTerminalNode("Canceled order.\n\n"); } purchasingItemSlot = null; return false; } purchasingItemSlot = null; if (array.Length == 0 || array[0] != "reserved") { return true; } if (array.Length == 1) { __result = BuildTerminalNodeHome(); return false; } string text2 = text.Substring(9); reservedItemSlotData = TryGetReservedItemSlot(text2); if (reservedItemSlotData != null) { if (SessionManager.IsItemSlotUnlocked(reservedItemSlotData)) { Plugin.LogWarning("Attempted to start purchase on reserved item slot that was already unlocked. Item slot: " + reservedItemSlotData.slotName); __result = BuildTerminalNodeAlreadyUnlocked(reservedItemSlotData); } else if (terminalInstance.groupCredits < reservedItemSlotData.purchasePrice) { Plugin.LogWarning("Attempted to start purchase with insufficient credits. Current credits: " + terminalInstance.groupCredits + ". Item slot price: " + reservedItemSlotData.purchasePrice); __result = BuildTerminalNodeInsufficientFunds(reservedItemSlotData); } else { Plugin.Log("Started purchasing reserved item slot: " + reservedItemSlotData.slotName); purchasingItemSlot = reservedItemSlotData; __result = BuildTerminalNodeConfirmDenyPurchase(reservedItemSlotData); } return false; } Plugin.LogWarning("Attempted to start purchase on invalid reserved item slot. Item slot: " + text2); __result = BuildTerminalNodeInvalidReservedItemSlot(text2); return false; } private static TerminalNode BuildTerminalNodeHome() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown return new TerminalNode { displayText = "[ReservedItemSlots]\n\nStore\n------------------------------\n[[[reservedItemSlotsSelectionList]]]\n\n", clearPreviousText = true, acceptAnything = false }; } private static TerminalNode BuildTerminalNodeConfirmDenyPurchase(ReservedItemSlotData itemSlotData) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown TerminalNode val = new TerminalNode(); val.displayText = "You have requested to purchase a reserved item slot for $" + itemSlotData.purchasePrice + " credits.\n> [" + itemSlotData.slotDisplayName + "]\n\n"; val.isConfirmationNode = true; val.acceptAnything = false; val.clearPreviousText = true; TerminalNode val2 = val; val2.displayText = val2.displayText + "Credit balance: $" + terminalInstance.groupCredits + "\n"; val2.displayText += "\n"; val2.displayText += "Please CONFIRM or DENY.\n\n"; return val2; } private static TerminalNode BuildTerminalNodeOnPurchased(ReservedItemSlotData itemSlotData, int newGroupCredits) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown TerminalNode val = new TerminalNode { displayText = "You have successfully purchased a new reserved item slot!\n> [" + itemSlotData.slotDisplayName + "]\n\n", buyUnlockable = true, clearPreviousText = true, acceptAnything = false, playSyncedClip = 0 }; val.displayText = val.displayText + "New credit balance: $" + newGroupCredits + "\n\n"; return val; } private static TerminalNode BuildTerminalNodeAlreadyUnlocked(ReservedItemSlotData itemSlot) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown return new TerminalNode { displayText = "You have already purchased this reserved item slot!\n> [" + itemSlot.slotDisplayName + "]\n\n", clearPreviousText = false, acceptAnything = false }; } private static TerminalNode BuildTerminalNodeInsufficientFunds(ReservedItemSlotData itemSlot) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown TerminalNode val = new TerminalNode(); val.displayText = "You could not afford this reserved item slot!\n> [" + itemSlot.slotDisplayName + "]\n\nCredit balance is $" + terminalInstance.groupCredits + "\n"; val.clearPreviousText = true; val.acceptAnything = false; TerminalNode val2 = val; val2.displayText = val2.displayText + "Price of reserved item slot is $" + itemSlot.purchasePrice + "\n\n"; return val2; } private static TerminalNode BuildTerminalNodeInvalidReservedItemSlot(string reservedItemSlotName = "") { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown TerminalNode val = new TerminalNode { displayText = "Reserved item slot does not exist.", clearPreviousText = false, acceptAnything = false }; if (reservedItemSlotName != "") { val.displayText = val.displayText + "\n\"" + reservedItemSlotName + "\""; } val.displayText += "\n"; return val; } private static TerminalNode BuildTerminalNodeHostDoesNotHaveMod(string itemSlotName = "") { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result typ