Decompiled source of Reloadable Hand Cannons v1.1.1
tony4twentys-Reloadable Hand Cannons.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.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using ExitGames.Client.Photon; using HarmonyLib; using Photon.Pun; using Photon.Realtime; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.SceneManagement; using UnityEngine.UI; using Zorro.Core; using Zorro.Core.Serizalization; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: AssemblyTitle("Reloadable_Hand_Cannons")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("Reloadable_Hand_Cannons")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("0f5e42e3-bb26-4c24-9f5b-39f5ae0867ad")] [assembly: AssemblyFileVersion("1.1.1.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.1.1.0")] [module: UnverifiableCode] namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } } namespace Hand_Cannon { public enum HandCannonAmmoType { Empty, Piton, NormalRope, AntiRope, Chain } [BepInPlugin("tony4twentys.Reloadable_Hand_Cannons", "Reloadable_Hand_Cannons", "1.1.1")] public class HandCannonPlugin : BaseUnityPlugin { public const string PluginGuid = "tony4twentys.Reloadable_Hand_Cannons"; public const string PluginName = "Reloadable_Hand_Cannons"; public const string PluginVersion = "1.1.1"; internal static ConfigEntry<float> PitonSpawnChanceConfig; internal static ConfigEntry<bool> AllowBackpackReloadConfig; internal static ConfigEntry<KeyCode> ReloadKeyConfig; private Harmony _harmony; public static HandCannonPlugin Instance { get; private set; } public static ManualLogSource Log { get; private set; } private void Awake() { //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Expected O, but got Unknown //IL_00fa: Unknown result type (might be due to invalid IL or missing references) Instance = this; Log = ((BaseUnityPlugin)this).Logger; PitonSpawnChanceConfig = ((BaseUnityPlugin)this).Config.Bind<float>("Spawn", "Piton Spawn Chance", 0.5f, "Chance (0.0 to 1.0) for a Hand Cannon (item 63) to spawn loaded with a piton instead of normal rope."); AllowBackpackReloadConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("Reload", "Allow Backpack Reload", true, "When true, pressing the reload key can consume ammo from a worn backpack."); ReloadKeyConfig = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Reload", "Reload Key", (KeyCode)114, "Press this key while holding an empty Hand Cannon to reload from inventory."); WarnIfConflictingModsLoaded(); _harmony = new Harmony("tony4twentys.Reloadable_Hand_Cannons"); try { _harmony.PatchAll(); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Reloadable Hand Cannons harmony patching failed: " + ex.Message)); } HandCannonReloadPickerUI.EnsureCreated(); HandCannonNetworkSync.EnsureProxy(); SceneManager.sceneLoaded += OnSceneLoaded; ((BaseUnityPlugin)this).Logger.LogInfo((object)($"Reloadable Hand Cannons loaded. Piton spawn chance: {PitonSpawnChanceConfig.Value:P0}. " + string.Format("Reload key: {0}. Backpack reload: {1}.", ReloadKeyConfig.Value, AllowBackpackReloadConfig.Value ? "enabled" : "disabled"))); } private void Update() { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) if (HandCannonReloadPickerUI.IsOpen) { if (Input.GetKeyDown((KeyCode)27) || Input.GetKeyDown(ReloadKeyConfig.Value)) { HandCannonReloadPickerUI.ForceClose(); } else { HandCannonReloadPickerUI.TryKeyboardSelect(); } } else { if (!Input.GetKeyDown(ReloadKeyConfig.Value)) { return; } Character localCharacter = Character.localCharacter; object obj; if (localCharacter == null) { obj = null; } else { CharacterData data = localCharacter.data; obj = ((data != null) ? data.currentItem : null); } if (!((Object)obj == (Object)null)) { Item currentItem = localCharacter.data.currentItem; RopeShooter component = ((Component)currentItem).GetComponent<RopeShooter>(); if (HandCannonHelper.IsHandCannon(currentItem) && HandCannonHelper.IsEmptyForReload(currentItem, component) && !currentItem.isUsingPrimary) { HandCannonReloadExecutor.TryManualReload(localCharacter); } } } } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { HandCannonUi.InvalidateFont(); HandCannonReloadPickerUI.ForceClose(); HandCannonIcon.QueueLiveRefresh(); } private void OnDestroy() { SceneManager.sceneLoaded -= OnSceneLoaded; Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } HandCannonReloadPickerUI.DestroyInstance(); Instance = null; Log = null; } private static void WarnIfConflictingModsLoaded() { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { string name = assemblies[i].GetName().Name; if (string.Equals(name, "Piton Launcher", StringComparison.Ordinal) || string.Equals(name, "Reloadable Rope Canons", StringComparison.Ordinal) || string.Equals(name, "Hand Cannon", StringComparison.Ordinal)) { Log.LogWarning((object)("Detected '" + name + "' — disable it to avoid Harmony conflicts with Reloadable Hand Cannons.")); } } } } internal static class HandCannonDataEntryKey { public static readonly DataEntryKey LoadedAmmoType = (DataEntryKey)74; public static readonly DataEntryKey BridgeFrame = (DataEntryKey)75; public static readonly DataEntryKey BridgeLauncherType = (DataEntryKey)76; } internal static class GameItemIds { public const ushort RopeCannonItemId = 63; public const ushort AntiRopeCannonItemId = 64; public const ushort ChainLauncherItemId = 17; public const ushort AntiRopeSpoolItemId = 1; public const ushort RopeSpoolItemId = 65; public const ushort ClimbingSpikeItemId = 18; } internal static class BridgeLauncherCompat { private const string BridgeLauncherTypeName = "Bridge_Launcher.BridgeLauncherDataEntryKey"; private const string LauncherTypeFieldName = "LauncherType"; private static int _resolveAttempts; private static bool _hasKey; private static DataEntryKey _launcherTypeKey; public static bool IsBridgeLauncher(Item item) { return IsBridgeLauncher(item, ((Object)(object)item != (Object)null) ? item.data : null); } public static bool IsBridgeLauncher(Item item, ItemInstanceData data) { if (HasOurBridgeFlag(item, data)) { return true; } if (HasForeignBridgeFlag(item, data)) { RememberBridgeFrame(item, HandCannonInventoryHelper.FindSlotForItem(item)); return true; } return false; } public static void CaptureIdentity(Item item) { if ((Object)(object)item != (Object)null && HasForeignBridgeFlag(item, item.data)) { RememberBridgeFrame(item, HandCannonInventoryHelper.FindSlotForItem(item)); } } public static void RequestHostTag(Item item) { if ((Object)(object)item == (Object)null) { return; } try { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { Type type = assemblies[i].GetType("Bridge_Launcher.BridgeNet"); if (!(type == null)) { MethodInfo method = type.GetMethod("ScheduleHostTag", BindingFlags.Static | BindingFlags.Public); if (method != null) { method.Invoke(null, new object[1] { item }); } break; } } } catch (Exception ex) { ManualLogSource log = HandCannonPlugin.Log; if (log != null) { log.LogWarning((object)("[Bridge] host tag request failed: " + ex.Message)); } } } public static void CopyBridgeFrameToSlot(Item item, ItemSlot slot) { if (!((Object)(object)item == (Object)null) && slot != null && IsBridgeLauncher(item)) { RememberBridgeFrame(item, slot); } } private static bool HasOurBridgeFlag(Item item, ItemInstanceData data) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)item != (Object)null && item.HasData(HandCannonDataEntryKey.BridgeFrame)) { IntItemData data2 = item.GetData<IntItemData>(HandCannonDataEntryKey.BridgeFrame); if (data2 != null && data2.Value != 0) { return true; } } return ReadOurBridgeFlag(data); } private static bool ReadOurBridgeFlag(ItemInstanceData data) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) if (data == null || !data.HasData(HandCannonDataEntryKey.BridgeFrame)) { return false; } IntItemData val = default(IntItemData); if (data.TryGetDataEntry<IntItemData>(HandCannonDataEntryKey.BridgeFrame, ref val) && val != null) { return val.Value != 0; } return false; } private static bool HasForeignBridgeFlag(Item item, ItemInstanceData data) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) if (HasBoolFlag(item, data, HandCannonDataEntryKey.BridgeLauncherType)) { return true; } if (!TryGetLauncherTypeKey(out var key)) { return false; } try { if ((Object)(object)item != (Object)null && item.HasData(key)) { BoolItemData data2 = item.GetData<BoolItemData>(key); if (data2 != null && data2.Value) { return true; } } BoolItemData val = default(BoolItemData); if (data != null && data.HasData(key) && data.TryGetDataEntry<BoolItemData>(key, ref val)) { return val?.Value ?? false; } } catch { } return false; } private static bool HasBoolFlag(Item item, ItemInstanceData data, DataEntryKey key) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: 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) try { if ((Object)(object)item != (Object)null && item.HasData(key)) { BoolItemData data2 = item.GetData<BoolItemData>(key); if (data2 != null && data2.Value) { return true; } } BoolItemData val = default(BoolItemData); if (data != null && data.HasData(key) && data.TryGetDataEntry<BoolItemData>(key, ref val)) { return val?.Value ?? false; } } catch { } return false; } private static void RememberBridgeFrame(Item item, ItemSlot slot) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown if ((Object)(object)item != (Object)null) { item.GetData<IntItemData>(HandCannonDataEntryKey.BridgeFrame).Value = 1; } if (slot != null) { if (slot.data == null) { slot.data = new ItemInstanceData(Guid.NewGuid()); } ItemDataHelper.SetIntEntry(slot.data, HandCannonDataEntryKey.BridgeFrame, 1); } } private static bool TryGetLauncherTypeKey(out DataEntryKey key) { //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Expected I4, but got Unknown //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) if (!_hasKey && _resolveAttempts < 8) { _resolveAttempts++; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { Type type = assembly.GetType("Bridge_Launcher.BridgeLauncherDataEntryKey"); if (type == null && assembly.GetName().Name != null && assembly.GetName().Name.IndexOf("Bridge", StringComparison.OrdinalIgnoreCase) >= 0) { type = assembly.GetType("Bridge_Shooter.BridgeLauncherDataEntryKey"); } if (type == null) { continue; } FieldInfo field = type.GetField("LauncherType", BindingFlags.Static | BindingFlags.Public); if (!(field == null)) { object value = field.GetValue(null); if (value is DataEntryKey) { _launcherTypeKey = (DataEntryKey)value; _hasKey = true; } break; } } } key = (DataEntryKey)(int)_launcherTypeKey; return _hasKey; } } internal static class HandCannonHelper { public static Item GetItem(RopeShooter shooter) { if ((Object)(object)shooter == (Object)null) { return null; } return ((ItemComponent)shooter).item ?? ((Component)shooter).GetComponent<Item>(); } public static Item GetItem(VineShooter vine) { if ((Object)(object)vine == (Object)null) { return null; } return ((ItemComponent)vine).item ?? ((Component)vine).GetComponent<Item>(); } public static bool IsChainLauncher(Item item) { if ((Object)(object)item != (Object)null && item.itemID == 17) { return (Object)(object)((Component)item).GetComponent<VineShooter>() != (Object)null; } return false; } public static bool IsHandCannon(Item item) { if ((Object)(object)item == (Object)null) { return false; } if (IsChainLauncher(item)) { return true; } if ((Object)(object)((Component)item).GetComponent<RopeShooter>() == (Object)null) { return false; } if (item.itemID != 63) { return item.itemID == 64; } return true; } public static bool HasCharge(Item item) { if ((Object)(object)item == (Object)null) { return false; } if (IsChainLauncher(item)) { return !ChainLooksSpent(item); } RopeShooter component = ((Component)item).GetComponent<RopeShooter>(); if ((Object)(object)component != (Object)null) { return component.HasAmmo; } if (item.HasData((DataEntryKey)2)) { OptionableIntItemData data = item.GetData<OptionableIntItemData>((DataEntryKey)2); if (data != null && data.HasData) { return data.Value > 0; } } return true; } public static bool HasSpentUses(Item item) { if ((Object)(object)item == (Object)null || !item.HasData((DataEntryKey)2)) { return false; } OptionableIntItemData data = item.GetData<OptionableIntItemData>((DataEntryKey)2); if (data != null && data.HasData) { return data.Value <= 0; } return false; } public static bool ChainLooksSpent(Item item) { if ((Object)(object)item == (Object)null) { return true; } if (HasSpentUses(item)) { return true; } VineShooter component = ((Component)item).GetComponent<VineShooter>(); if ((Object)(object)component != (Object)null && (Object)(object)component.disableOnFire != (Object)null) { _ = component.disableOnFire.activeSelf; return false; } return false; } public static bool CanTagItems() { if (PhotonNetwork.InRoom) { return PhotonNetwork.IsMasterClient; } return true; } public static Item GetActionItem(ItemActionBase action) { if (action == null) { return null; } return ((Component)action).GetComponent<Item>(); } public static bool IsEmptyForReload(Item item, RopeShooter shooter) { if ((Object)(object)item == (Object)null) { return false; } if (HandCannonAmmoHelper.GetEffectiveAmmo(item) == HandCannonAmmoType.Empty) { return true; } if ((Object)(object)shooter != (Object)null) { if (!shooter.HasAmmo) { return true; } OptionableIntItemData data = item.GetData<OptionableIntItemData>((DataEntryKey)2); if (data != null && data.HasData && data.Value <= 0) { return true; } return false; } return !HasCharge(item); } } internal static class ItemUsabilityHelper { private static readonly FieldInfo OverrideUsabilityField = AccessTools.Field(typeof(Item), "overrideUsability"); public static void SetOverrideUsability(Item item, bool usable) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)item == (Object)null) && !(OverrideUsabilityField == null)) { OverrideUsabilityField.SetValue(item, Optionable<bool>.Some(usable)); } } } internal static class HandCannonFireHelper { public static void ConsumeFiredShot(RopeShooter shooter, Item item) { ConsumeFiredShot(item, shooter); } public static void ConsumeFiredShot(Item item, RopeShooter shooter) { if (!((Object)(object)item == (Object)null) && HandCannonHelper.IsHandCannon(item)) { if ((Object)(object)shooter == (Object)null) { shooter = ((Component)item).GetComponent<RopeShooter>(); } ItemSlot slot = HandCannonInventoryHelper.FindSlotForItem(item); HandCannonAmmoHelper.SetLoadedAmmo(item, slot, HandCannonAmmoType.Empty); HandCannonAmmoHelper.ClearUses(item); VineShooter component = ((Component)item).GetComponent<VineShooter>(); if ((Object)(object)component != (Object)null && (Object)(object)component.disableOnFire != (Object)null) { component.disableOnFire.SetActive(false); } if ((Object)(object)shooter != (Object)null) { shooter.cantReFire = false; ((ItemComponent)shooter).OnInstanceDataSet(); } HandCannonStateSync.Sync(item, shooter); HandCannonNetworkSync.PushAmmoState(item, slot, item.holderCharacter); } } } internal static class HandCannonStateSync { public static void Sync(Item item, RopeShooter shooter) { HandCannonAntigravSync.Sync(item, shooter); HandCannonVisualSync.Sync(item, shooter); } } internal static class HandCannonNetworkSync { public const byte EventCode = 191; public const int ProtocolVersion = 100; private const byte SubAmmoSync = 0; private const byte SubAmmoRequest = 1; private static HandCannonNetProxy _proxy; private static readonly Dictionary<int, HandCannonAmmoType> AmmoByViewId = new Dictionary<int, HandCannonAmmoType>(); private static readonly HashSet<int> DeferredTagInFlight = new HashSet<int>(); public static PhotonView GetItemView(Item item) { if ((Object)(object)item == (Object)null) { return null; } try { PhotonView photonView = ((MonoBehaviourPun)item).photonView; if ((Object)(object)photonView != (Object)null) { return photonView; } } catch { } return ((Component)item).GetComponent<PhotonView>(); } public static void RememberAmmo(int viewId, HandCannonAmmoType ammo) { if (viewId > 0) { AmmoByViewId[viewId] = ammo; } } public static bool TryGetRememberedAmmo(int viewId, out HandCannonAmmoType ammo) { return AmmoByViewId.TryGetValue(viewId, out ammo); } public static bool TryGetRememberedAmmo(Item item, out HandCannonAmmoType ammo) { ammo = HandCannonAmmoType.Empty; PhotonView itemView = GetItemView(item); if ((Object)(object)itemView != (Object)null) { return TryGetRememberedAmmo(itemView.ViewID, out ammo); } return false; } public static void EnsureProxy() { //IL_0013: 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_001e: Expected O, but got Unknown if (!((Object)(object)_proxy != (Object)null)) { GameObject val = new GameObject("ReloadableHandCannonsNet"); Object.DontDestroyOnLoad((Object)val); _proxy = val.AddComponent<HandCannonNetProxy>(); } } public static void StartCoroutineOnProxy(IEnumerator routine) { EnsureProxy(); if ((Object)(object)_proxy != (Object)null && routine != null) { ((MonoBehaviour)_proxy).StartCoroutine(routine); } } public static void PushAmmoState(Item item, ItemSlot slot, Character holder) { if ((Object)(object)item != (Object)null && slot != null) { HandCannonAmmoHelper.CopyAmmoToSlot(item, slot); } PushItemInstanceData(item); BroadcastAmmo(item); SyncHolderInventory(holder); } public static void PushItemInstanceData(Item item) { if (item?.data == null || !PhotonNetwork.InRoom) { return; } PhotonView itemView = GetItemView(item); if ((Object)(object)itemView == (Object)null || (!itemView.IsMine && !PhotonNetwork.IsMasterClient)) { return; } RememberAmmo(itemView.ViewID, HandCannonAmmoHelper.GetLoadedAmmo(item)); try { itemView.RPC("SetItemInstanceDataRPC", (RpcTarget)1, new object[1] { item.data }); } catch (Exception ex) { ManualLogSource log = HandCannonPlugin.Log; if (log != null) { log.LogWarning((object)("[Sync] SetItemInstanceDataRPC failed: " + ex.Message)); } } BroadcastAmmo(item); } public static void BroadcastAmmo(Item item) { //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_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Expected O, but got Unknown if ((Object)(object)item == (Object)null || !PhotonNetwork.InRoom) { return; } PhotonView itemView = GetItemView(item); if ((Object)(object)itemView == (Object)null || (!itemView.IsMine && !PhotonNetwork.IsMasterClient)) { return; } HandCannonAmmoType loadedAmmo = HandCannonAmmoHelper.GetLoadedAmmo(item); RememberAmmo(itemView.ViewID, loadedAmmo); try { PhotonNetwork.RaiseEvent((byte)191, (object)new object[4] { 100, (byte)0, itemView.ViewID, (int)loadedAmmo }, new RaiseEventOptions { Receivers = (ReceiverGroup)0 }, SendOptions.SendReliable); } catch (Exception ex) { ManualLogSource log = HandCannonPlugin.Log; if (log != null) { log.LogWarning((object)("[Sync] RaiseEvent ammo failed: " + ex.Message)); } } } public static void ApplyRemoteAmmo(int itemViewId, HandCannonAmmoType ammo) { RememberAmmo(itemViewId, ammo); PhotonView val = PhotonView.Find(itemViewId); if (!((Object)(object)val == (Object)null)) { Item component = ((Component)val).GetComponent<Item>(); if (HandCannonHelper.IsHandCannon(component)) { HandCannonAmmoHelper.SetLoadedAmmo(component, null, ammo); RopeShooter component2 = ((Component)component).GetComponent<RopeShooter>(); HandCannonStateSync.Sync(component, component2); } } } public static bool TryApplyRememberedAmmo(Item item) { if (!TryGetRememberedAmmo(item, out var ammo)) { return false; } if (HandCannonAmmoHelper.GetLoadedAmmo(item) == ammo) { return true; } HandCannonAmmoHelper.SetLoadedAmmo(item, null, ammo); return true; } public static void RequestAmmoFromHost(Item item) { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown if ((Object)(object)item == (Object)null || !PhotonNetwork.InRoom || PhotonNetwork.IsMasterClient) { return; } PhotonView itemView = GetItemView(item); if ((Object)(object)itemView == (Object)null) { return; } try { PhotonNetwork.RaiseEvent((byte)191, (object)new object[4] { 100, (byte)1, itemView.ViewID, 0 }, new RaiseEventOptions { Receivers = (ReceiverGroup)2 }, SendOptions.SendReliable); } catch (Exception ex) { ManualLogSource log = HandCannonPlugin.Log; if (log != null) { log.LogWarning((object)("[Sync] ammo request failed: " + ex.Message)); } } } public static void RespondToAmmoRequest(int itemViewId) { if (PhotonNetwork.IsMasterClient) { PhotonView val = PhotonView.Find(itemViewId); Item item = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<Item>() : null); if (HandCannonHelper.IsHandCannon(item)) { BroadcastAmmo(item); PushItemInstanceData(item); } } } public static void BroadcastAllHandCannons() { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) if (!PhotonNetwork.IsMasterClient) { return; } Item[] array = Resources.FindObjectsOfTypeAll<Item>(); foreach (Item val in array) { if (HandCannonHelper.IsHandCannon(val) && !((Object)(object)((Component)val).gameObject == (Object)null)) { Scene scene = ((Component)val).gameObject.scene; if (((Scene)(ref scene)).IsValid()) { BroadcastAmmo(val); PushItemInstanceData(val); } } } } public static void SyncHolderInventory(Character character) { //IL_0072: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)((character != null) ? character.player : null) == (Object)null || !PhotonNetwork.InRoom || !character.IsLocal) { return; } PhotonView component = ((Component)character.player).GetComponent<PhotonView>(); if ((Object)(object)component == (Object)null) { return; } try { InventorySyncData val = default(InventorySyncData); ((InventorySyncData)(ref val))..ctor(character.player.itemSlots, character.player.backpackSlot, character.player.tempFullSlot); component.RPC("SyncInventoryRPC", (RpcTarget)1, new object[2] { IBinarySerializable.ToManagedArray<InventorySyncData>(val), false }); } catch (Exception ex) { ManualLogSource log = HandCannonPlugin.Log; if (log != null) { log.LogWarning((object)("[Sync] SyncInventoryRPC failed: " + ex.Message)); } } } public static void PreserveAmmoOnStash(Item item) { if (!HandCannonHelper.IsHandCannon(item)) { return; } Character holderCharacter = item.holderCharacter; if (!((Object)(object)((holderCharacter != null) ? holderCharacter.player : null) == (Object)null)) { ItemSlot val = HandCannonInventoryHelper.FindSlotForItem(item); if (val != null && !val.IsEmpty()) { HandCannonAmmoHelper.CopyAmmoToSlot(item, val); SyncHolderInventory(item.holderCharacter); } } } public static void PreserveAmmoBeforeDrop(Item item) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) if (!HandCannonHelper.IsHandCannon(item)) { return; } Character holderCharacter = item.holderCharacter; if ((Object)(object)((holderCharacter != null) ? holderCharacter.player : null) == (Object)null) { return; } ItemSlot val = HandCannonInventoryHelper.FindSlotForItem(item); if (val == null || val.IsEmpty() || !item.HasData(HandCannonDataEntryKey.LoadedAmmoType)) { return; } try { HandCannonAmmoHelper.CopyAmmoToSlot(item, val); } catch (Exception ex) { ManualLogSource log = HandCannonPlugin.Log; if (log != null) { log.LogWarning((object)("[Sync] preserve ammo before drop failed: " + ex.Message)); } } } public static void ScheduleSpawnResync(Item item) { StartCoroutineOnProxy(SpawnResyncRoutine(item)); } public static void ScheduleClientCatchup(Item item) { StartCoroutineOnProxy(ClientCatchupRoutine(item)); } public static bool TryBeginDeferredTag(int viewId) { return DeferredTagInFlight.Add(viewId); } public static void EndDeferredTag(int viewId) { DeferredTagInFlight.Remove(viewId); } private static IEnumerator SpawnResyncRoutine(Item item) { yield return null; if ((Object)(object)item != (Object)null) { PushItemInstanceData(item); } yield return (object)new WaitForSeconds(0.35f); if ((Object)(object)item != (Object)null) { PushItemInstanceData(item); } } private static IEnumerator ClientCatchupRoutine(Item item) { float[] waits = new float[3] { 0.05f, 0.2f, 0.5f }; for (int i = 0; i < waits.Length; i++) { yield return (object)new WaitForSeconds(waits[i]); if ((Object)(object)item == (Object)null) { break; } if (TryApplyRememberedAmmo(item) || HandCannonAmmoHelper.GetLoadedAmmo(item) != HandCannonAmmoType.Empty) { RopeShooter component = ((Component)item).GetComponent<RopeShooter>(); HandCannonStateSync.Sync(item, component); break; } RequestAmmoFromHost(item); } } internal static void HandleEvent(EventData eventData) { if (eventData == null || eventData.Code != 191 || !(eventData.CustomData is object[] array) || array.Length < 3 || Convert.ToInt32(array[0]) != 100) { return; } byte b = Convert.ToByte(array[1]); int itemViewId = Convert.ToInt32(array[2]); switch (b) { case 1: RespondToAmmoRequest(itemViewId); break; case 0: if (array.Length >= 4) { HandCannonAmmoType ammo = (HandCannonAmmoType)Convert.ToInt32(array[3]); ApplyRemoteAmmo(itemViewId, ammo); } break; } } } internal sealed class HandCannonNetProxy : MonoBehaviourPunCallbacks, IOnEventCallback { public override void OnEnable() { ((MonoBehaviourPunCallbacks)this).OnEnable(); PhotonNetwork.AddCallbackTarget((object)this); } public override void OnDisable() { PhotonNetwork.RemoveCallbackTarget((object)this); ((MonoBehaviourPunCallbacks)this).OnDisable(); } public void OnPlayerEnteredRoom(Player _) { if (PhotonNetwork.IsMasterClient) { ((MonoBehaviour)this).StartCoroutine(BroadcastAfterJoin()); } } public void OnEvent(EventData photonEvent) { HandCannonNetworkSync.HandleEvent(photonEvent); } private IEnumerator BroadcastAfterJoin() { yield return (object)new WaitForSeconds(0.5f); HandCannonNetworkSync.BroadcastAllHandCannons(); } } internal static class HandCannonAmmoHelper { public static HandCannonAmmoType GetLoadedAmmo(Item item) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)item == (Object)null) { return HandCannonAmmoType.Empty; } if (item.HasData(HandCannonDataEntryKey.LoadedAmmoType)) { return (HandCannonAmmoType)item.GetData<IntItemData>(HandCannonDataEntryKey.LoadedAmmoType).Value; } if (HandCannonNetworkSync.TryGetRememberedAmmo(item, out var ammo)) { return ammo; } ItemSlot val = HandCannonInventoryHelper.FindSlotForItem(item); if (val != null && !val.IsEmpty() && val.data != null) { return GetLoadedAmmo(val.data); } return HandCannonAmmoType.Empty; } public static HandCannonAmmoType GetLoadedAmmo(ItemInstanceData data) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) if (data == null || !data.HasData(HandCannonDataEntryKey.LoadedAmmoType)) { return HandCannonAmmoType.Empty; } IntItemData val = default(IntItemData); if (data.TryGetDataEntry<IntItemData>(HandCannonDataEntryKey.LoadedAmmoType, ref val)) { return (HandCannonAmmoType)val.Value; } return HandCannonAmmoType.Empty; } public static void SetLoadedAmmo(Item item, ItemSlot slot, HandCannonAmmoType ammoType) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected O, but got Unknown if (slot == null) { slot = HandCannonInventoryHelper.FindSlotForItem(item); } if ((Object)(object)item != (Object)null) { item.GetData<IntItemData>(HandCannonDataEntryKey.LoadedAmmoType).Value = (int)ammoType; PhotonView itemView = HandCannonNetworkSync.GetItemView(item); if ((Object)(object)itemView != (Object)null) { HandCannonNetworkSync.RememberAmmo(itemView.ViewID, ammoType); } } if (slot != null) { if (slot.data == null) { slot.data = new ItemInstanceData(Guid.NewGuid()); } ItemDataHelper.SetIntEntry(slot.data, HandCannonDataEntryKey.LoadedAmmoType, (int)ammoType); } HandCannonIcon.QueueLiveRefresh(); } public static bool HasExplicitAmmoType(Item item) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)item != (Object)null && item.HasData(HandCannonDataEntryKey.LoadedAmmoType)) { return true; } HandCannonAmmoType ammo; return HandCannonNetworkSync.TryGetRememberedAmmo(item, out ammo); } public static void ClearUses(Item item) { if ((Object)(object)item == (Object)null) { return; } RopeShooter component = ((Component)item).GetComponent<RopeShooter>(); if ((Object)(object)component != (Object)null) { ((ItemComponent)component).GetData<IntItemData>((DataEntryKey)12, (Func<IntItemData>)(() => ItemDataHelper.CreateIntItemData(0))).Value = 0; } OptionableIntItemData data = item.GetData<OptionableIntItemData>((DataEntryKey)2); if (data != null) { data.HasData = true; data.Value = 0; } item.SetUseRemainingPercentage(0f); } public static void CopyAmmoToSlot(Item item, ItemSlot slot) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown if (!((Object)(object)item == (Object)null) && slot != null) { HandCannonAmmoType loadedAmmo = GetLoadedAmmo(item); if (slot.data == null) { slot.data = new ItemInstanceData((item.data != null) ? item.data.guid : Guid.NewGuid()); } ItemDataHelper.SetIntEntry(slot.data, HandCannonDataEntryKey.LoadedAmmoType, (int)loadedAmmo); BridgeLauncherCompat.CopyBridgeFrameToSlot(item, slot); } } public static string GetAmmoLabel(HandCannonAmmoType ammoType) { return ammoType switch { HandCannonAmmoType.Piton => "piton", HandCannonAmmoType.NormalRope => "rope", HandCannonAmmoType.AntiRope => "anti-grav rope", HandCannonAmmoType.Chain => "chain", _ => "empty", }; } public static string GetDisplayName(HandCannonAmmoType ammoType) { return ammoType switch { HandCannonAmmoType.Piton => "Piton Cannon", HandCannonAmmoType.NormalRope => "Rope Cannon", HandCannonAmmoType.AntiRope => "Anti-Rope Cannon", HandCannonAmmoType.Chain => "Chain Cannon", _ => "Hand Cannon", }; } public static string GetDisplayName(Item item, HandCannonAmmoType ammoType) { return GetDisplayName(item, ((Object)(object)item != (Object)null) ? item.data : null, ammoType); } public static string GetDisplayName(Item item, ItemInstanceData data, HandCannonAmmoType ammoType) { Item item2 = FindLiveItemForName(item, data); if (ammoType == HandCannonAmmoType.Chain && BridgeLauncherCompat.IsBridgeLauncher(item2, data)) { return "Bridge Cannon"; } return GetDisplayName(ammoType); } public static HandCannonAmmoType ResolveLoadedAmmoForName(Item item, ItemInstanceData data) { //IL_0062: Unknown result type (might be due to invalid IL or missing references) Item val = FindLiveItemForName(item, data); HandCannonAmmoType loadedAmmo = GetLoadedAmmo(val); if (loadedAmmo != HandCannonAmmoType.Empty) { return loadedAmmo; } loadedAmmo = GetLoadedAmmo(data); if (loadedAmmo != HandCannonAmmoType.Empty) { return loadedAmmo; } loadedAmmo = GetLoadedAmmo(item); if (loadedAmmo != HandCannonAmmoType.Empty) { return loadedAmmo; } Item item2 = (((Object)(object)val != (Object)null) ? val : item); if (HandCannonHelper.HasSpentUses(item2)) { return HandCannonAmmoType.Empty; } if (HandCannonHelper.IsChainLauncher(item2) && !HandCannonHelper.ChainLooksSpent(item2)) { return HandCannonAmmoType.Chain; } if (!HasExplicitAmmoType(item)) { if (data == null) { return HandCannonAmmoType.Empty; } data.HasData(HandCannonDataEntryKey.LoadedAmmoType); } return HandCannonAmmoType.Empty; } private static Item FindLiveItemForName(Item item, ItemInstanceData data) { Guid guid = Guid.Empty; if (data != null) { guid = data.guid; } else if ((Object)(object)item != (Object)null && item.data != null) { guid = item.data.guid; } if (guid == Guid.Empty) { return item; } List<Item> aLL_ACTIVE_ITEMS = Item.ALL_ACTIVE_ITEMS; if (aLL_ACTIVE_ITEMS != null) { for (int i = 0; i < aLL_ACTIVE_ITEMS.Count; i++) { Item val = aLL_ACTIVE_ITEMS[i]; if ((Object)(object)val != (Object)null && val.data != null && val.data.guid == guid) { return val; } } } return item; } public static HandCannonAmmoType GetEffectiveAmmo(Item item) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) HandCannonAmmoType loadedAmmo = GetLoadedAmmo(item); if (loadedAmmo != HandCannonAmmoType.Empty) { return loadedAmmo; } if (HandCannonHelper.HasSpentUses(item)) { return HandCannonAmmoType.Empty; } if (HandCannonHelper.IsChainLauncher(item) && !HandCannonHelper.ChainLooksSpent(item)) { return HandCannonAmmoType.Chain; } if (!HasExplicitAmmoType(item)) { if (!((Object)(object)item != (Object)null)) { return HandCannonAmmoType.Empty; } item.HasData(HandCannonDataEntryKey.LoadedAmmoType); } return HandCannonAmmoType.Empty; } } internal static class ItemDataHelper { public static void SetIntEntry(ItemInstanceData data, DataEntryKey key, int value) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown //IL_0027: Unknown result type (might be due to invalid IL or missing references) IntItemData val = default(IntItemData); if (data.TryGetDataEntry<IntItemData>(key, ref val)) { val.Value = value; return; } IntItemData val2 = new IntItemData(); ((DataEntryValue)val2).Init(); val2.Value = value; data.RegisterEntry<IntItemData>(key, val2); } public static void SetOptionableIntEntry(ItemInstanceData data, DataEntryKey key, int value) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown //IL_0035: Unknown result type (might be due to invalid IL or missing references) OptionableIntItemData val = default(OptionableIntItemData); if (data.TryGetDataEntry<OptionableIntItemData>(key, ref val)) { val.HasData = true; val.Value = value; return; } OptionableIntItemData val2 = new OptionableIntItemData(); ((DataEntryValue)val2).Init(); val2.HasData = true; val2.Value = value; data.RegisterEntry<OptionableIntItemData>(key, val2); } public static void SetFloatEntry(ItemInstanceData data, DataEntryKey key, float value) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown //IL_0027: Unknown result type (might be due to invalid IL or missing references) FloatItemData val = default(FloatItemData); if (data.TryGetDataEntry<FloatItemData>(key, ref val)) { val.Value = value; return; } FloatItemData val2 = new FloatItemData(); ((DataEntryValue)val2).Init(); val2.Value = value; data.RegisterEntry<FloatItemData>(key, val2); } public static IntItemData CreateIntItemData(int value) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Expected O, but got Unknown IntItemData val = new IntItemData(); ((DataEntryValue)val).Init(); val.Value = value; return val; } } internal static class HandCannonAntigravSync { private static float? _cachedIntensity; public static void Sync(Item item, RopeShooter shooter) { if ((Object)(object)item == (Object)null) { return; } bool num = HandCannonHelper.HasCharge(item) && HandCannonAmmoHelper.GetLoadedAmmo(item) == HandCannonAmmoType.AntiRope; Antigrav val = ((Component)item).GetComponent<Antigrav>(); if (num) { if ((Object)(object)val == (Object)null) { val = ((Component)item).gameObject.AddComponent<Antigrav>(); } val.intensity = GetAntigravIntensity(); } else if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)val); } } private static float GetAntigravIntensity() { if (_cachedIntensity.HasValue) { return _cachedIntensity.Value; } Item[] array = Resources.FindObjectsOfTypeAll<Item>(); foreach (Item val in array) { if (!((Object)(object)val == (Object)null) && val.itemID == 64) { Antigrav component = ((Component)val).GetComponent<Antigrav>(); if ((Object)(object)component != (Object)null) { _cachedIntensity = component.intensity; return _cachedIntensity.Value; } } } _cachedIntensity = 1f; return _cachedIntensity.Value; } } internal static class HandCannonVisualSync { private const string PitonVisualObjectName = "HandCannonPitonVisual"; private const string SwappedRopeVisualObjectName = "HandCannonSwappedRopeVisual"; private const string SwappedHarpoonVisualObjectName = "HandCannonSwappedHarpoonVisual"; private const string AmmoAttachObjectName = "HandCannonAmmoAttach"; private const string PitonClimbingSpikeChildName = "ClimbingSpike"; private static readonly Vector3 PitonClimbingSpikeLocalPosition = new Vector3(-0.0304f, -27.3382f, -4.3815f); private static readonly Vector3 PitonClimbingSpikeLocalEuler = new Vector3(270f, 180f, 0f); private static readonly Vector3 PitonClimbingSpikeLocalScale = Vector3.one; private static readonly Dictionary<int, bool> SwappedRopeIsAntiVisual = new Dictionary<int, bool>(); private static readonly Dictionary<int, bool> ChainAttachIsAntiVisual = new Dictionary<int, bool>(); private static int GetVisualId(RopeShooter shooter, Transform hideOnFire) { if ((Object)(object)shooter != (Object)null) { return ((Object)shooter).GetInstanceID(); } if (!((Object)(object)hideOnFire != (Object)null)) { return 0; } return ((Object)hideOnFire).GetInstanceID(); } private static GameObject GetHideOnFire(RopeShooter shooter) { if ((Object)(object)shooter == (Object)null) { return null; } Transform val = FindNamedChild(((Component)shooter).transform, "HideOnFire") ?? FindNamedChild(((Component)shooter).transform, "hideOnFire"); if ((Object)(object)val != (Object)null) { return ((Component)val).gameObject; } Transform val2 = FindNamedChild(((Component)shooter).transform, "Harpoon"); if (!((Object)(object)val2 != (Object)null) || !((Object)(object)val2.parent != (Object)null)) { return null; } return ((Component)val2.parent).gameObject; } private static Transform FindNamedChild(Transform root, string childName) { if ((Object)(object)root == (Object)null) { return null; } Transform val = root.Find(childName); if ((Object)(object)val != (Object)null) { return val; } for (int i = 0; i < root.childCount; i++) { Transform val2 = FindNamedChild(root.GetChild(i), childName); if ((Object)(object)val2 != (Object)null) { return val2; } } return null; } public static void Sync(Item item, RopeShooter shooter) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) if (!HandCannonHelper.IsHandCannon(item)) { return; } HandCannonAmmoType handCannonAmmoType = HandCannonAmmoHelper.GetLoadedAmmo(item); bool flag = item.HasData(HandCannonDataEntryKey.LoadedAmmoType) && handCannonAmmoType == HandCannonAmmoType.Empty; bool flag2 = HandCannonHelper.HasCharge(item); if (handCannonAmmoType == HandCannonAmmoType.Empty && flag2 && !flag) { if (HandCannonHelper.IsChainLauncher(item)) { handCannonAmmoType = HandCannonAmmoType.Chain; } else if (item.itemID == 64) { handCannonAmmoType = HandCannonAmmoType.AntiRope; } } VineShooter component = ((Component)item).GetComponent<VineShooter>(); if ((Object)(object)component != (Object)null) { SyncChainLauncherVisuals(component, handCannonAmmoType, flag2, flag); return; } GameObject hideOnFire = GetHideOnFire(shooter); if ((Object)(object)hideOnFire == (Object)null) { return; } Transform transform = hideOnFire.transform; int visualId = GetVisualId(shooter, transform); if (!flag2 || handCannonAmmoType == HandCannonAmmoType.Empty) { ClearRuntimeVisuals(visualId, transform); if (!flag2 || flag) { SetActiveIfPresent(FindDirectChild(transform, "Harpoon"), active: false); SetActiveIfPresent(FindDirectChild(transform, "Rope"), active: false); SetActiveIfPresent(FindDirectChild(transform, "Piton"), active: false); } return; } if (!hideOnFire.activeSelf) { ClearRuntimeVisuals(visualId, transform); return; } Transform val = FindDirectChild(transform, "Harpoon"); Transform val2 = FindDirectChild(transform, "Rope"); Transform val3 = EnsurePitonVisual(transform, val); bool flag3 = handCannonAmmoType == HandCannonAmmoType.Piton; bool flag4 = handCannonAmmoType == HandCannonAmmoType.NormalRope || handCannonAmmoType == HandCannonAmmoType.AntiRope; SetActiveIfPresent(val, flag4); SetActiveIfPresent(val3, flag3); if (flag4) { ApplyRopeVisual(item, shooter, transform, val2, handCannonAmmoType, visualId); } else { HideSwappedRopeVisual(visualId, transform); SetActiveIfPresent(val2, active: false); } HideUnmanagedLoadedChildren(transform, val, val2, val3, flag3, flag4); } private static void ApplyRopeVisual(Item item, RopeShooter shooter, Transform hideOnFire, Transform nativeRope, HandCannonAmmoType ammo, int visualId) { bool flag = item.itemID == 64; bool flag2 = ammo == HandCannonAmmoType.AntiRope; if ((!flag || flag2) && !(!flag && flag2)) { HideSwappedRopeVisual(visualId, hideOnFire); SetActiveIfPresent(nativeRope, active: true); return; } Transform referenceRopeTransform = GetReferenceRopeTransform(flag2); if ((Object)(object)referenceRopeTransform == (Object)null) { HideSwappedRopeVisual(visualId, hideOnFire); SetActiveIfPresent(nativeRope, active: true); } else { Transform transform = EnsureSwappedRopeVisual(visualId, hideOnFire, nativeRope, referenceRopeTransform, flag2); SetActiveIfPresent(nativeRope, active: false); SetActiveIfPresent(transform, active: true); } } private static void SyncChainLauncherVisuals(VineShooter vine, HandCannonAmmoType ammo, bool hasCharge, bool explicitlyEmpty) { if ((Object)(object)vine == (Object)null) { return; } Item item = HandCannonHelper.GetItem(vine); GameObject val = vine.disableOnFire; if ((Object)(object)val == (Object)null) { Transform val2 = FindNamedChild(((Component)vine).transform, "disableOnFire") ?? FindNamedChild(((Component)vine).transform, "DisableOnFire"); val = (((Object)(object)val2 != (Object)null) ? ((Component)val2).gameObject : null); } DestroyLegacyChainRootOverlays(((Component)vine).transform); if ((Object)(object)val != (Object)null) { DestroyLegacyChainRootOverlays(val.transform); } bool flag = ammo == HandCannonAmmoType.Chain; bool flag2 = hasCharge && ammo == HandCannonAmmoType.Piton; bool flag3 = hasCharge && (ammo == HandCannonAmmoType.NormalRope || ammo == HandCannonAmmoType.AntiRope); if (!hasCharge || ammo == HandCannonAmmoType.Empty || flag) { if ((Object)(object)val != (Object)null) { val.SetActive(flag); } SetAmmoAttachActive(vine, active: false); return; } if ((Object)(object)val != (Object)null) { val.SetActive(false); } bool wantsAntiVisual = ammo == HandCannonAmmoType.AntiRope; Transform val3 = EnsureGoldAmmoAttach(vine, item, wantsAntiVisual); if ((Object)(object)val3 == (Object)null) { HandCannonPlugin.Log.LogWarning((object)"[Visual] chain launcher could not clone rope-cannon HideOnFire; ammo overlay skipped."); if ((Object)(object)val != (Object)null) { val.SetActive(true); } return; } ((Component)val3).gameObject.SetActive(true); int instanceID = ((Object)val3).GetInstanceID(); Transform val4 = FindDirectChild(val3, "Harpoon") ?? FindNamedChild(val3, "Harpoon"); Transform val5 = FindDirectChild(val3, "Rope") ?? FindNamedChild(val3, "Rope"); Transform val6 = EnsurePitonVisual(val3, val4); SetActiveIfPresent(val4, flag3); SetActiveIfPresent(val6, flag2); if (flag3) { ApplyRopeVisual(item, null, val3, val5, ammo, instanceID); } else { HideSwappedRopeVisual(instanceID, val3); SetActiveIfPresent(val5, active: false); } HideUnmanagedLoadedChildren(val3, val4, val5, val6, flag2, flag3); } private static void DestroyLegacyChainRootOverlays(Transform root) { if (!((Object)(object)root == (Object)null)) { DestroyNamedChild(root, "HandCannonPitonVisual"); DestroyNamedChild(root, "HandCannonSwappedRopeVisual"); DestroyNamedChild(root, "HandCannonSwappedHarpoonVisual"); } } private static void DestroyNamedChild(Transform parent, string childName) { if (!((Object)(object)parent == (Object)null)) { Transform val = parent.Find(childName); if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)((Component)val).gameObject); } } } private static void SetAmmoAttachActive(VineShooter vine, bool active) { if (!((Object)(object)vine == (Object)null)) { SetActiveIfPresent(((Component)vine).transform.Find("HandCannonAmmoAttach"), active); } } private static Transform EnsureGoldAmmoAttach(VineShooter vine, Item item, bool wantsAntiVisual) { if ((Object)(object)vine == (Object)null || (Object)(object)item == (Object)null) { return null; } int instanceID = ((Object)vine).GetInstanceID(); Transform val = item.transform.Find("HandCannonAmmoAttach"); if ((Object)(object)val != (Object)null && ChainAttachIsAntiVisual.TryGetValue(instanceID, out var value) && value == wantsAntiVisual) { return val; } if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)((Component)val).gameObject); ChainAttachIsAntiVisual.Remove(instanceID); } RopeShooter shooter; if (wantsAntiVisual) { AntiRopeCannonReference.TryGetShooter(out shooter); } else { NormalRopeCannonReference.TryGetShooter(out shooter); } if ((Object)(object)shooter == (Object)null && wantsAntiVisual) { NormalRopeCannonReference.TryGetShooter(out shooter); } GameObject hideOnFire = GetHideOnFire(shooter); Item item2 = HandCannonHelper.GetItem(shooter); if ((Object)(object)hideOnFire == (Object)null || (Object)(object)item2 == (Object)null) { return null; } GameObject obj = Object.Instantiate<GameObject>(hideOnFire, item.transform); ((Object)obj).name = "HandCannonAmmoAttach"; ApplyItemRelativeTransform(obj.transform, hideOnFire.transform, item2.transform); StripGameplayComponents(obj); DestroyLegacyChainRootOverlays(obj.transform); ChainAttachIsAntiVisual[instanceID] = wantsAntiVisual; return obj.transform; } private static void ApplyItemRelativeTransform(Transform target, Transform source, Transform sourceItem) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_006a: 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_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)target == (Object)null) && !((Object)(object)source == (Object)null) && !((Object)(object)sourceItem == (Object)null)) { target.localPosition = sourceItem.InverseTransformPoint(source.position); target.localRotation = Quaternion.Inverse(sourceItem.rotation) * source.rotation; Vector3 lossyScale = source.lossyScale; Vector3 lossyScale2 = sourceItem.lossyScale; target.localScale = new Vector3(SafeDivide(lossyScale.x, lossyScale2.x), SafeDivide(lossyScale.y, lossyScale2.y), SafeDivide(lossyScale.z, lossyScale2.z)); } } private static float SafeDivide(float numerator, float denominator) { if (Mathf.Abs(denominator) < 0.0001f) { return numerator; } return numerator / denominator; } private static Transform GetReferenceRopeTransform(bool wantsAntiVisual) { RopeShooter shooter; if (wantsAntiVisual) { AntiRopeCannonReference.TryGetShooter(out shooter); } else { NormalRopeCannonReference.TryGetShooter(out shooter); } GameObject hideOnFire = GetHideOnFire(shooter); if ((Object)(object)hideOnFire == (Object)null) { return null; } return FindDirectChild(hideOnFire.transform, "Rope"); } private static Transform EnsureSwappedRopeVisual(int visualId, Transform hideOnFire, Transform nativeRope, Transform referenceRope, bool wantsAntiVisual) { Transform val = hideOnFire.Find("HandCannonSwappedRopeVisual"); if ((Object)(object)val != (Object)null && SwappedRopeIsAntiVisual.TryGetValue(visualId, out var value) && value == wantsAntiVisual) { return val; } if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)((Component)val).gameObject); SwappedRopeIsAntiVisual.Remove(visualId); } GameObject obj = Object.Instantiate<GameObject>(((Component)referenceRope).gameObject, hideOnFire); ((Object)obj).name = "HandCannonSwappedRopeVisual"; ApplyAnchorTransform(obj.transform, nativeRope ?? referenceRope); StripGameplayComponents(obj); SwappedRopeIsAntiVisual[visualId] = wantsAntiVisual; return obj.transform; } private static Transform EnsurePitonVisual(Transform hideOnFire, Transform harpoonAnchor) { Transform val = FindDirectChild(hideOnFire, "Piton"); val = val ?? hideOnFire.Find("HandCannonPitonVisual"); if ((Object)(object)val != (Object)null) { ApplyPitonClimbingSpikeTransform(val); return val; } GameObject val2 = Resources.Load<GameObject>("0_Items/Piton"); if ((Object)(object)val2 == (Object)null && PitonPrefabCache.EnsureInitialized(HandCannonPlugin.Log)) { val2 = Resources.Load<GameObject>(PitonPrefabCache.PrefabPath); } if ((Object)(object)val2 == (Object)null) { return null; } GameObject obj = Object.Instantiate<GameObject>(val2, hideOnFire); ((Object)obj).name = "HandCannonPitonVisual"; ApplyAnchorTransform(obj.transform, harpoonAnchor); StripGameplayComponents(obj); ApplyPitonClimbingSpikeTransform(obj.transform); return obj.transform; } private static void ApplyPitonClimbingSpikeTransform(Transform pitonVisualRoot) { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)pitonVisualRoot == (Object)null) { return; } Transform val = pitonVisualRoot.Find("ClimbingSpike"); if ((Object)(object)val == (Object)null) { for (int i = 0; i < pitonVisualRoot.childCount; i++) { Transform child = pitonVisualRoot.GetChild(i); if (((Object)child).name.IndexOf("ClimbingSpike", StringComparison.OrdinalIgnoreCase) >= 0) { val = child; break; } } } if (!((Object)(object)val == (Object)null)) { val.localPosition = PitonClimbingSpikeLocalPosition; val.localRotation = Quaternion.Euler(PitonClimbingSpikeLocalEuler); val.localScale = PitonClimbingSpikeLocalScale; } } private static void ApplyAnchorTransform(Transform visual, Transform anchor) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)visual == (Object)null)) { if ((Object)(object)anchor == (Object)null) { visual.localPosition = Vector3.zero; visual.localRotation = Quaternion.identity; visual.localScale = Vector3.one; } else { visual.localPosition = anchor.localPosition; visual.localRotation = anchor.localRotation; visual.localScale = anchor.localScale; } } } private static void HideSwappedRopeVisual(int visualId, Transform hideOnFire) { SetActiveIfPresent(hideOnFire.Find("HandCannonSwappedRopeVisual"), active: false); SwappedRopeIsAntiVisual.Remove(visualId); } private static void ClearRuntimeVisuals(int visualId, Transform hideOnFire) { HideSwappedRopeVisual(visualId, hideOnFire); SetActiveIfPresent(hideOnFire.Find("HandCannonPitonVisual"), active: false); SetActiveIfPresent(FindDirectChild(hideOnFire, "Piton"), active: false); } private static void HideUnmanagedLoadedChildren(Transform hideOnFire, Transform harpoon, Transform nativeRope, Transform pitonVisual, bool showPiton, bool showRopeShot) { for (int i = 0; i < hideOnFire.childCount; i++) { Transform child = hideOnFire.GetChild(i); if (!((Object)(object)child == (Object)(object)harpoon) && !((Object)(object)child == (Object)(object)nativeRope) && !((Object)(object)child == (Object)(object)pitonVisual) && !(((Object)child).name == "HandCannonSwappedRopeVisual") && !(((Object)child).name == "SpawnPoint")) { bool active = (showPiton && ((Object)child).name == "Piton") || (showRopeShot && (((Object)child).name == "Harpoon" || ((Object)child).name == "Rope")); ((Component)child).gameObject.SetActive(active); } } } private static Transform FindDirectChild(Transform parent, string childName) { if ((Object)(object)parent == (Object)null) { return null; } return parent.Find(childName); } private static void SetActiveIfPresent(Transform transform, bool active) { if (transform != null) { ((Component)transform).gameObject.SetActive(active); } } private static void StripGameplayComponents(GameObject root) { if ((Object)(object)root == (Object)null) { return; } Component[] componentsInChildren = root.GetComponentsInChildren<Component>(true); foreach (Component val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && !(val is Transform) && !(val is MeshFilter) && !(val is MeshRenderer) && !(val is SkinnedMeshRenderer) && !(val is ParticleSystem) && !(val is ParticleSystemRenderer) && !(val is LineRenderer) && !(val is TrailRenderer)) { Object.Destroy((Object)(object)val); } } } } internal static class AntiRopeCannonReference { private static RopeShooter _cachedShooter; private static bool _loggedFailure; public static bool IsAvailable() { RopeShooter shooter; return TryGetShooter(out shooter); } public static bool TryGetShooter(out RopeShooter shooter) { if ((Object)(object)_cachedShooter != (Object)null) { shooter = _cachedShooter; return true; } if (TryResolveFromLoadedItems(out shooter) || TryResolveFromResources(out shooter) || TryResolveFromLoadedAssets(out shooter)) { _cachedShooter = shooter; return true; } if (!_loggedFailure) { _loggedFailure = true; ManualLogSource log = HandCannonPlugin.Log; if (log != null) { log.LogWarning((object)"Could not resolve anti-rope cannon reference. Anti-grav spool reloads disabled until available."); } } shooter = null; return false; } private static bool TryResolveFromLoadedItems(out RopeShooter shooter) { shooter = null; Item[] array = Resources.FindObjectsOfTypeAll<Item>(); foreach (Item val in array) { if (!((Object)(object)val == (Object)null) && val.itemID == 64) { RopeShooter component = ((Component)val).GetComponent<RopeShooter>(); if ((Object)(object)component?.ropeAnchorWithRopePref != (Object)null) { shooter = component; return true; } } } return false; } private static bool TryResolveFromResources(out RopeShooter shooter) { shooter = null; string[] array = new string[3] { "0_Items/Anti-Rope Cannon", "0_Items/RopeShooterAnti", "0_Items/AntiRope Cannon" }; for (int i = 0; i < array.Length; i++) { GameObject val = Resources.Load<GameObject>(array[i]); shooter = ((val != null) ? val.GetComponent<RopeShooter>() : null); if ((Object)(object)shooter != (Object)null) { return true; } } GameObject[] array2 = Resources.LoadAll<GameObject>("0_Items/"); if (array2 == null) { return false; } GameObject[] array3 = array2; foreach (GameObject val2 in array3) { if ((Object)(object)val2 == (Object)null) { continue; } Item component = val2.GetComponent<Item>(); if (!((Object)(object)component == (Object)null) && component.itemID == 64) { shooter = val2.GetComponent<RopeShooter>(); if ((Object)(object)shooter != (Object)null) { return true; } } } return false; } private static bool TryResolveFromLoadedAssets(out RopeShooter shooter) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) shooter = null; RopeShooter[] array = Resources.FindObjectsOfTypeAll<RopeShooter>(); foreach (RopeShooter val in array) { if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).gameObject == (Object)null)) { Scene scene = ((Component)val).gameObject.scene; if (!((Scene)(ref scene)).IsValid() && ((Component)val).GetComponent<Item>()?.itemID == 64) { shooter = val; return true; } } } return false; } public static float GetShotSegments() { if (TryGetShooter(out var shooter) && shooter.length > 0f) { return shooter.length; } return 30f; } public static GameObject GetAnchorPrefab() { if (!TryGetShooter(out var shooter)) { return null; } return shooter.ropeAnchorWithRopePref; } public static Item GetItem() { if (!TryGetShooter(out var shooter)) { return null; } return ((Component)shooter).GetComponent<Item>(); } } internal static class NormalRopeCannonReference { private static RopeShooter _cachedShooter; private static bool _loggedFailure; public static bool TryGetShooter(out RopeShooter shooter) { if ((Object)(object)_cachedShooter != (Object)null) { shooter = _cachedShooter; return true; } if (TryResolveFromLoadedItems(out shooter) || TryResolveFromResources(out shooter) || TryResolveFromLoadedAssets(out shooter)) { _cachedShooter = shooter; return true; } if (!_loggedFailure) { _loggedFailure = true; ManualLogSource log = HandCannonPlugin.Log; if (log != null) { log.LogWarning((object)"Could not resolve normal rope cannon reference. Anti-grav Hand Cannon normal reloads may fire anti rope."); } } shooter = null; return false; } private static bool TryResolveFromLoadedItems(out RopeShooter shooter) { shooter = null; Item[] array = Resources.FindObjectsOfTypeAll<Item>(); foreach (Item val in array) { if (!((Object)(object)val == (Object)null) && val.itemID == 63) { RopeShooter component = ((Component)val).GetComponent<RopeShooter>(); if ((Object)(object)component?.ropeAnchorWithRopePref != (Object)null) { shooter = component; return true; } } } return false; } private static bool TryResolveFromResources(out RopeShooter shooter) { shooter = null; string[] array = new string[3] { "0_Items/Rope Cannon", "0_Items/RopeShooter", "0_Items/Rope CannonItem" }; for (int i = 0; i < array.Length; i++) { GameObject val = Resources.Load<GameObject>(array[i]); shooter = ((val != null) ? val.GetComponent<RopeShooter>() : null); if ((Object)(object)shooter?.ropeAnchorWithRopePref != (Object)null) { return true; } } GameObject[] array2 = Resources.LoadAll<GameObject>("0_Items/"); if (array2 == null) { return false; } GameObject[] array3 = array2; foreach (GameObject val2 in array3) { if ((Object)(object)val2 == (Object)null) { continue; } Item component = val2.GetComponent<Item>(); if (!((Object)(object)component == (Object)null) && component.itemID == 63) { shooter = val2.GetComponent<RopeShooter>(); if ((Object)(object)shooter?.ropeAnchorWithRopePref != (Object)null) { return true; } } } return false; } private static bool TryResolveFromLoadedAssets(out RopeShooter shooter) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) shooter = null; RopeShooter[] array = Resources.FindObjectsOfTypeAll<RopeShooter>(); foreach (RopeShooter val in array) { if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).gameObject == (Object)null)) { Scene scene = ((Component)val).gameObject.scene; if (!((Scene)(ref scene)).IsValid() && ((Component)val).GetComponent<Item>()?.itemID == 63) { shooter = val; return true; } } } return false; } public static GameObject GetAnchorPrefab() { if (!TryGetShooter(out var shooter)) { return null; } return shooter.ropeAnchorWithRopePref; } public static Item GetItem() { if (!TryGetShooter(out var shooter)) { return null; } return ((Component)shooter).GetComponent<Item>(); } } internal static class RopeSpoolLengthHelper { public const float MetersPerSegment = 0.25f; public const float DefaultCannonShotSegments = 30f; public const float OutOfRopeSegmentThreshold = 2f; public const float DefaultSpoolStartFuel = 60f; private const float SegmentComparisonEpsilon = 0.01f; internal const float SegmentEpsilon = 0.01f; public static float SegmentsToMeters(float segments) { return segments * 0.25f; } public static float GetCannonShotSegments(RopeShooter shooter) { if ((Object)(object)shooter == (Object)null || shooter.length <= 0f) { return 30f; } return shooter.length; } public static float GetSpoolStartFuel(ItemSlot slot) { if ((Object)(object)((slot != null) ? slot.prefab : null) == (Object)null) { return 60f; } RopeSpool component = ((Component)slot.prefab).GetComponent<RopeSpool>(); if (!((Object)(object)component != (Object)null)) { return 60f; } return component.ropeStartFuel; } public static float GetRemainingSegments(ItemSlot slot) { if (slot == null || slot.IsEmpty()) { return 0f; } float spoolStartFuel = GetSpoolStartFuel(slot); ItemInstanceData data = slot.data; if (data == null) { return spoolStartFuel; } FloatItemData val = default(FloatItemData); if (data.TryGetDataEntry<FloatItemData>((DataEntryKey)10, ref val)) { return Mathf.Max(0f, val.Value); } FloatItemData val2 = default(FloatItemData); if (data.TryGetDataEntry<FloatItemData>((DataEntryKey)11, ref val2)) { return Mathf.Max(0f, val2.Value * spoolStartFuel); } return spoolStartFuel; } public static bool HasReloadableLength(float segments) { return segments > 2.01f; } public static bool CanFullyReload(float segments, float requiredSegments) { return segments + 0.01f >= requiredSegments; } } internal readonly struct RopeReloadPlan { public ItemSlot PartialSlot { get; } public float SegmentsToDeduct { get; } public IReadOnlyList<ItemSlot> SlotsToConsumeEntirely { get; } public bool IsAntiRopeAmmo { get; } public bool UsesPartialSlot => PartialSlot != null; public bool IsValid { get { if (!UsesPartialSlot) { return SlotsToConsumeEntirely.Count > 0; } return true; } } public RopeReloadPlan(ItemSlot partialSlot, float segmentsToDeduct, IReadOnlyList<ItemSlot> slotsToConsumeEntirely, bool isAntiRopeAmmo) { PartialSlot = partialSlot; SegmentsToDeduct = segmentsToDeduct; SlotsToConsumeEntirely = slotsToConsumeEntirely ?? Array.Empty<ItemSlot>(); IsAntiRopeAmmo = isAntiRopeAmmo; } } internal sealed class HandCannonReloadPlan { public HandCannonAmmoType AmmoType { get; private set; } public ItemSlot PitonSlot { get; private set; } public RopeReloadPlan RopePlan { get; private set; } public string DisplayLabel { get; private set; } public bool IsPiton => AmmoType == HandCannonAmmoType.Piton; public bool IsValid { get { if (!IsPiton) { return RopePlan.IsValid; } return PitonSlot != null; } } public static HandCannonReloadPlan ForPiton(ItemSlot slot) { return new HandCannonReloadPlan { AmmoType = HandCannonAmmoType.Piton, PitonSlot = slot, DisplayLabel = $"Piton — slot {slot.itemSlotID}" }; } public static HandCannonReloadPlan ForRope(RopeReloadPlan ropePlan, HandCannonAmmoType ammoType, string displayLabel) { return new HandCannonReloadPlan { AmmoType = ammoType, RopePlan = ropePlan, DisplayLabel = displayLabel }; } } internal static class HandCannonInventoryHelper { private const byte TempInventorySlotId = 250; public static ItemSlot FindSlotForItem(Item item) { //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: 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) Character val = ((item != null) ? item.holderCharacter : null); if ((Object)(object)((val != null) ? val.player : null) == (Object)null) { return null; } if (item.data != null && item.data.guid != Guid.Empty) { ItemSlot val2 = FindSlotByGuid(val, item.data.guid); if (val2 != null) { return val2; } } CharacterData data = val.data; if ((Object)(object)((data != null) ? data.currentItem : null) == (Object)(object)item) { Optionable<byte> valueOrDefault = (val.refs?.items?.currentSelectedSlot).GetValueOrDefault(); if (valueOrDefault.IsSome) { ItemSlot itemSlot = val.player.GetItemSlot(valueOrDefault.Value); if (itemSlot != null && !itemSlot.IsEmpty() && (Object)(object)itemSlot.prefab != (Object)null && itemSlot.prefab.itemID == item.itemID) { return itemSlot; } } } return null; } private static ItemSlot FindSlotByGuid(Character holder, Guid guid) { if ((Object)(object)((holder != null) ? holder.player : null) == (Object)null || guid == Guid.Empty) { return null; } ItemSlot val = FindSlotByGuid(holder.player.itemSlots, guid); if (val != null) { return val; } if (SlotHasGuid(holder.player.tempFullSlot, guid)) { return holder.player.tempFullSlot; } if (SlotHasGuid((ItemSlot)(object)holder.player.backpackSlot, guid)) { return (ItemSlot)(object)holder.player.backpackSlot; } BackpackData val2 = default(BackpackData); if (holder.player.backpackSlot != null && !((ItemSlot)holder.player.backpackSlot).IsEmpty() && ((ItemSlot)holder.player.backpackSlot).data != null && ((ItemSlot)holder.player.backpackSlot).data.TryGetDataEntry<BackpackData>((DataEntryKey)7, ref val2)) { return FindSlotByGuid(val2.itemSlots, guid); } return null; } private static ItemSlot FindSlotByGuid(ItemSlot[] slots, Guid guid) { if (slots == null) { return null; } foreach (ItemSlot val in slots) { if (SlotHasGuid(val, guid)) { return val; } } return null; } private static bool SlotHasGuid(ItemSlot slot, Guid guid) { if (slot != null && !slot.IsEmpty() && slot.data != null) { return slot.data.guid == guid; } return false; } public static bool IsHandheldPitonPrefab(Item prefab, ItemInstanceData slotData = null) { if ((Object)(object)prefab == (Object)null || (Object)(object)((Component)prefab).GetComponent<RopeShooter>() != (Object)null) { return false; } if (prefab.itemID == 18 || (Object)(object)((Component)prefab).GetComponent<ClimbingSpikeComponent>() != (Object)null) { IntItemData val = default(IntItemData); if (slotData != null && slotData.TryGetDataEntry<IntItemData>((DataEntryKey)1, ref val) && val.Value > 0) { return false; } return true; } string text = ((Object)((Component)prefab).gameObject).name ?? string.Empty; if (text.IndexOf("ClimbingSpike", StringComparison.OrdinalIgnoreCase) < 0) { return text.IndexOf("Piton", StringComparison.OrdinalIgnoreCase) >= 0; } return true; } public static bool IsRopeSpoolPrefab(Item prefab) { if ((Object)(object)prefab == (Object)null || (Object)(object)((Component)prefab).GetComponent<RopeShooter>() != (Object)null) { return false; } if ((Object)(object)((Component)prefab).GetComponent<RopeSpool>() != (Object)null) { return true; } if (prefab.itemID == 65 || prefab.itemID == 1) { return true; } return (((Object)((Component)prefab).gameObject).name ?? string.Empty).IndexOf("Rope Spool", StringComparison.OrdinalIgnoreCase) >= 0; } public static bool IsAntiRopeSpoolPrefab(Item prefab) { if ((Object)(object)prefab == (Object)null) { return false; } RopeSpool component = ((Component)prefab).GetComponent<RopeSpool>(); if (component != null && component.isAntiRope) { return true; } if (prefab.itemID == 1) { return true; } return (((Object)((Component)prefab).gameObject).name ?? string.Empty).IndexOf("Anti-Rope Spool", StringComparison.OrdinalIgnoreCase) >= 0; } public static void RefreshPitonTracking(Character character) { if ((Object)(object)character?.refs?.items != (Object)null && character.player?.itemSlots != null) { character.refs.items.UpdateClimbingSpikeCount(character.player.itemSlots); } } public static List<ItemSlot> GetPitonSlotsInOrder(Character character) { List<ItemSlot> list = new List<ItemSlot>(); if ((Object)(object)character == (Object)null) { return list; } RefreshPitonTracking(character); AppendPitonSlots(character.player?.itemSlots, list); if (character.player?.tempFullSlot != null && !character.player.tempFullSlot.IsEmpty() && IsHandheldPitonPrefab(character.player.tempFullSlot.prefab, character.player.tempFullSlot.data)) { list.Add(character.player.tempFullSlot); } if (HandCannonPlugin.AllowBackpackReloadConfig.Value) { AppendBackpackPitonSlots(character, list); } return list; } private static void AppendPitonSlots(ItemSlot[] slots, List<ItemSlot> pitonSlots) { if (slots == null) { return; } foreach (ItemSlot val in slots) { if (val != null && !val.IsEmpty() && IsHandheldPitonPrefab(val.prefab, val.data)) { pitonSlots.Add(val); } } } private static void AppendBackpackPitonSlots(Character character, List<ItemSlot> pitonSlots) { if (!((Object)(object)((character != null) ? character.player : null) == (Object)null) && character.player.backpackSlot != null && !((ItemSlot)character.player.backpackSlot).IsEmpty()) { ItemInstanceData data = ((ItemSlot)character.player.backpackSlot).data; BackpackData val = default(BackpackData); if (data != null && data.TryGetDataEntry<BackpackData>((DataEntryKey)7, ref val)) { AppendPitonSlots(val.itemSlots, pitonSlots); } } } public static List<ItemSlot> GetRopeSpoolSlotsInOrder(Character character) { List<ItemSlot> list = new List<ItemSlot>(); if ((Object)(object)character == (Object)null) { return list; } AppendRopeSlots(character.player?.itemSlots, list); if (character.player?.tempFullSlot != null && !character.player.tempFullSlot.IsEmpty() && IsRopeSpoolPrefab(character.player.tempFullSlot.prefab)) { list.Add(character.player.tempFullSlot); } if (HandCannonPlugin.AllowBackpackReloadConfig.Value) { AppendBackpackRopeSlots(character, list); } return list; } private static void AppendRopeSlots(ItemSlot[] slots, List<ItemSlot> ropeSlots) { if (slots == null) { return; } foreach (ItemSlot val in slots) { if (val != null && !val.IsEmpty() && IsRopeSpoolPrefab(val.prefab)) { ropeSlots.Add(val); } } } private static void AppendBackpackRopeSlots(Character character, List<ItemSlot> ropeSlots) { if (!((Object)(object)((character != null) ? character.player : null) == (Object)null) && character.player.backpackSlot != null && !((ItemSlot)character.player.backpackSlot).IsEmpty()) { ItemInstanceData data = ((ItemSlot)character.player.backpackSlot).data; BackpackData val = default(BackpackData); if (data != null && data.TryGetDataEntry<BackpackData>((DataEntryKey)7, ref val)) { AppendRopeSlots(val.itemSlots, ropeSlots); } } } public static bool TryBuildBestRopePlan(List<ItemSlot> ropeSlots, float requiredSegments, bool isAntiRopeAmmo, out RopeReloadPlan plan) { if (HasPartialSpoolsForAmmoType(ropeSlots, requiredSegments, isAntiRopeAmmo) && TryBuildCombinedReloadPlan(ropeSlots, requiredSegments, isAntiRopeAmmo, out plan)) { return true; } if (TryBuildSingleSpoolPlan(ropeSlots, requiredSegments, isAntiRopeAmmo, out plan)) { return true; } return TryBuildCombinedReloadPlan(ropeSlots, requiredSegments, isAntiRopeAmmo, out plan); } private static bool HasPartialSpoolsForAmmoType(List<ItemSlot> ropeSlots, float requiredSegments, bool isAntiRopeAmmo) { foreach (ItemSlot ropeSlot in ropeSlots) { if (IsAntiRopeSpoolPrefab(ropeSlot.prefab) == isAntiRopeAmmo) { float remainingSegments = RopeSpoolLengthHelper.GetRemainingSegments(ropeSlot); if (RopeSpoolLengthHelper.HasReloadableLength(remainingSegments) && !RopeSpoolLengthHelper.CanFullyReload(remainingSegments, requiredSegments)) { return true; } } } return false; } private static bool TryBuildSingleSpoolPlan(List<ItemSlot> ropeSlots, float requiredSegments, bool isAntiRopeAmmo, out RopeReloadPlan plan) { plan = default(RopeReloadPlan); foreach (ItemSlot ropeSlot in ropeSlots) { if (IsAntiRopeSpoolPrefab(ropeSlot.prefab) == isAntiRopeAmmo && RopeSpoolLengthHelper.CanFullyReload(RopeSpoolLengthHelper.GetRemainingSegments(ropeSlot), requiredSegments)) { plan = new RopeReloadPlan(ropeSlot, requiredSegments, Array.Empty<ItemSlot>(), isAntiRopeAmmo); return true; } } return false; } private static bool TryBuildCombinedReloadPlan(List<ItemSlot> ropeSlots, float requiredSegments, bool isAntiRopeAmmo, out RopeReloadPlan plan) { plan = default(RopeReloadPlan); float num = 0f; List<ItemSlot> list = new List<ItemSlot>(); foreach (ItemSlot ropeSlot in ropeSlots) { if (IsAntiRopeSpoolPrefab(ropeSlot.prefab) != isAntiRopeAmmo) { continue; } float remainingSegments = RopeSpoolLengthHelper.GetRemainingSegments(ropeSlot); if (RopeSpoolLengthHelper.HasReloadableLength(remainingSegments)) { list.Add(ropeSlot); num += remainingSegments; if (RopeSpoolLengthHelper.CanFullyReload(num, requiredSegments)) { plan = BuildCombinedReloadPlan(list, requiredSegments, isAntiRopeAmmo); return plan.IsValid; } } } return false; } private static RopeReloadPlan BuildCombinedReloadPlan(List<ItemSlot> spoolsInOrder, float requiredSegments, bool isAntiRopeAmmo) { float num = requiredSegments; List<ItemSlot> list = new List<ItemSlot>(); ItemSlot val = null; float segmentsToDeduct = 0f; foreach (ItemSlot item in spoolsInOrder) { float remainingSegments = RopeSpoolLengthHelper.GetRemainingSegments(item); if (!(remainingSegments <= 2f)) { if (!(num + 0.01f >= remainingSegments)) { val = item; segmentsToDeduct = num; num = 0f; break; } list.Add(item); num -= remainingSegments; } } if (num > 0.01f) { return default(RopeReloadPlan); } if (val != null) { return new RopeReloadPlan(val, segmentsToDeduct, list, isAntiRopeAmmo); } return new RopeReloadPlan(null, 0f, list, isAntiRopeAmmo); } public static string BuildRopePlanLabel(RopeReloadPlan plan, float requiredSegments, HandCannonAmmoType ammoType) { string text = ((ammoType == HandCannonAmmoType.AntiRope) ? "Anti-grav rope" : "Rope"); float num = RopeSpoolLengthHelper.SegmentsToMeters(requiredSegments); if (plan.SlotsToConsumeEntirely.Count == 0 && plan.UsesPartialSlot) { float segments = RopeSpoolLengthHelper.GetRemainingSegments(plan.PartialSlot) - plan.SegmentsToDeduct; return $"{text} — {num:0.##}m from slot {plan.PartialSlot.itemSlotID} ({RopeSpoolLengthHelper.SegmentsToMeters(segments):0.##}m left after)"; } if (plan.SlotsToConsumeEntirely.Count > 0 && !plan.UsesPartialSlot) { return $"{text} — combine {plan.SlotsToConsumeEntirely.Count} spool(s) for {num:0.##}m"; } if (plan.SlotsToConsumeEntirely.Count > 0 && plan.UsesPartialSlot) { return $"{text} — combine {plan.SlotsToConsumeEntirely.Count + 1} spool(s) for {num:0.##}m"; } return $"{text} — {num:0.##}m shot"; } public static bool TryApplyRopePlan(Character character, RopeReloadPlan plan) { if ((Object)(object)character == (Object)null || !plan.IsValid) { return false; } bool flag = false; if (plan.UsesPartialSlot) { if (!TryDeductSegmentsFromSlot(character, plan.PartialSlot, plan.SegmentsToDeduct)) { return false; } flag = IsBackpackSlot(character, plan.PartialSlot); } foreach (ItemSlot item in plan.SlotsToConsumeEntirely) { if (!TryConsumeInventorySlot(character, item, syncBackpack: false)) { return false; } flag = flag || IsBackpackSlot(character, item); } if (flag) { SyncPlayerInventory(character); } return true; } public static bool TryConsumePitonSlot(Character character, ItemSlot slot) { if ((Object)(object)character == (Object)null || slot == null) { return false; } bool result = TryConsumeInventorySlot(character, slot, syncBackpack: true); RefreshPitonTracking(character); return result; } private static bool TryDeductSegmentsFromSlot(Character character, ItemSlot slot, float segmentsToDeduct) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown if ((Object)(object)character == (Object)null || slot == null || slot.IsEmpty() || segmentsToDeduct <= 0f) { return false; } float spoolStartFuel = RopeSpoolLengthHelper.GetSpoolStartFuel(slot); float num = RopeSpoolLengthHelper.GetRemainingSegments(slot) - segmentsToDeduct; if (num <= 2f) { return TryConsumeInventorySlot(character, slot, syncBackpack: false); } if (slot.data == null) { slot.data = new ItemInstanceData(Guid.NewGuid()); } ItemDataHelper.SetFloatEntry(slot.data, (DataEntryKey)10, num); float value = ((spoolStartFuel > 0f) ? Mathf.Clamp01(num / spoolStartFuel) : 0f); ItemDataHelper.SetFloatEntry(slot.data, (DataEntryKey)11, value); return true; } private static bool TryConsumeInventorySlot(Character character, ItemSlot slot, bool syncBackpack) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)((character != null) ? character.player : null) == (Object)null || slot == null) { return false; } try { if (slot.itemSlotID == 250) { character.player.EmptySlot(Optionable<byte>.Some((byte)250), true); } else if (IsBackpackSlot(character, slot)) { slot.EmptyOut(); if (syncBackpack) { SyncPlayerInventory(character); } } else { character.player.EmptySlot(Optionable<byte>.Some(slot.itemSlotID), true); } } catch (Exception ex) { HandCannonPlugin.Log.LogWarning((object)("[Reload] EmptySlot failed, using local EmptyOut: " + ex.Message)); slot.EmptyOut(); if (syncBackpack) { SyncPlayerInventory(character); } } if (!slot.IsEmpty()) { slot.EmptyOut(); } return slot.IsEmpty(); } private static void SyncPlayerInventory(Character character) { //IL_0062: Unknown result type (might be due to invalid IL or missing references) object obj; if (character == null) { obj = null; } else { Player player = character.player; obj = ((player != null) ? ((Component)player).GetComponent<PhotonView>() : null); } PhotonView val = (PhotonView)obj; if (!PhotonNetwork.IsMasterClient || (Object)(object)val == (Object)null) { return; } try { InventorySyncData val2 = default(InventorySyncData); ((InventorySyncData)(ref val2))..ctor(character.player.itemSlots, character.player.backpackSlot, character.player.tempFullSlot); val.RPC("SyncInventoryRPC", (RpcTarget)1, new object[2] { IBinarySerializable.ToManagedArray<InventorySyncData>(val2), false }); } catch (Exception ex) { HandCannonPlugin.Log.LogWarning((object)("[Reload] inventory sync skipped: " + ex.Message)); } } public static bool IsBackpackSlot(Character character, ItemSlot slot) { if ((Object)(object)((character != null) ? character.player : null) == (Object)null || slot == null || character.player.backpackSlot == null || ((ItemSlot)character.player.backpackSlot).IsEmpty()) { return false; } ItemInstanceData data = ((ItemSlot)character.player.backpackSlot).data; BackpackData val = default(BackpackData); if (data == null || !data.TryGetDataEntry<BackpackData>((DataEntryKey)7, ref val)) { return false; } ItemSlot[] itemSlots = val.itemSlots; for (int i = 0; i < itemSlots.Length; i++) { if (itemSlots[i] == slot) { return true; } } return false; } } internal static class HandCannonReloadPlanner { public static List<HandCannonReloadPlan> BuildAllValidPlans(Character character, RopeShooter shooter) { List<HandCannonReloadPlan> list = new List<HandCannonReloadPlan>(); if ((Object)(object)character == (Object)null) { return list; } foreach (ItemSlot item in HandCannonInventoryHelper.GetPitonSlotsInOrder(character)) { list.Add(HandCannonReloadPlan.ForPiton(item)); } List<ItemSlot> ropeSpoolSlotsInOrder = HandCannonInventoryHelper.GetRopeSpoolSlotsInOrder(character); float cannonShotSegments = RopeSpoolLengthHelper.GetCannonShotSegments(shooter); if (HandCannonInventoryHelper.TryBuildBestRopePlan(ropeSpoolSlotsInOrder, cannonShotSegments, isAntiRopeAmmo: false, out var plan)) { string displayLabel = HandCannonInventoryHelper.BuildRopePlanLabel(plan, cannonShotSegments, HandCannonAmmoType.NormalRope); list.Add(HandCannonReloadPlan.ForRope(plan, HandCannonAmmoType.NormalRope, displayLabel)); } float shotSegments = AntiRopeCannonReference.GetShotSegments(); if (CanUseAntiRopeAmmo(shooter) && HandCannonInventoryHelper.TryBuildBestRopePlan(ropeSpoolSlotsInOrder, shotSegments, isAntiRopeAmmo: true, out var plan2)) { string displayLabel2 = HandCannonInventoryHelper.BuildRopePlanLabel(plan2, shotSegments, HandCannonAmmoType.AntiRope); list.Add(HandCannonReloadPlan.ForRope(plan2, HandCannonAmmoType.AntiRope, displayLabel2)); } return CollapseDistinctAmmoTypes(list); } private static List<HandCannonReloadPlan> CollapseDistinctAmmoTypes(List<HandCannonReloadPlan> plans) { List<HandCannonReloadPlan> list = new List<HandCannonReloadPlan>(); HashSet<HandCannonAmmoType> hashSet = new HashSet<HandCannonAmmoType>(); foreach (HandCannonReloadPlan plan in plans) { if (hashSet.Add(plan.AmmoType)) { list.Add(plan); } } return list; } private static bool CanUseAntiRopeAmmo(RopeShooter shooter) { Item val = HandCannonHelper.GetItem(shooter); if ((Object)(object)val == (Object)null) { Character localCharacter = Character.localCharacter; object obj; if (localCharacter == null) { obj = null; } else { CharacterData data = localCharacter.data; obj = ((data != null) ? data.currentItem : null); } val = (Item)obj; } if (val?.itemID == 64) { return true; } return AntiRopeCannonReference.IsAvailable(); } } internal static class HandCannonReloadExecutor { public static bool TryManualReload(Character holder) { Character obj = holder; object obj2; if (obj == null) { obj2 = null; } else { CharacterData data = obj.data; obj2 = ((data != null) ? data.currentItem : null); } if ((Object)obj2 == (Object)null) { return false; } Item cannonItem = holder.data.currentItem; RopeShooter shooter = ((Component)cannonItem).GetComponent<RopeShooter>(); if (!HandCannonHelper.IsHandCannon(cannonItem) || !HandCannonHelper.IsEmptyForReload(cannonItem, shooter)) { return false; } List<HandCannonReloadPlan> list = HandCannonReloadPlanner.BuildAllValidPlans(holder, shooter); if (list.Count == 0) { return false; } if (list.Count == 1) { return ExecutePlan(holder, cannonItem, shooter, list[0]); } HandCannonReloadPickerUI.Show(list, delegate(HandCannonReloadPlan plan) { ExecutePlan(holder, cannonItem, shooter, plan); }); return true; } public static bool ExecutePlan(Character holder, Item cannonItem, RopeShooter shooter, HandCannonReloadPlan plan) { if ((Object)(object)holder == (Object)null || (Object)(object)cannonItem == (Object)null || plan == null || !plan.IsValid) { return false; } ItemSlot val = HandCannonInventoryHelper.FindSlotForItem(cannonItem); if (!ApplySlotDataReload(cannonItem, shooter, plan.AmmoType, val)) { return false; } if (!HandCannonHelper.HasCharge(cannonItem)) { HandCannonPlugin.Log.LogWarning((object)"[Reload] slot-data reload left Hand Cannon empty."); return false; } if (val != null && !val.IsEmpty()) { ResetCannonSlotForFreshShot(val, shooter, plan.AmmoType); } if (plan.IsPiton) { if (!HandCannonInventoryHelper.TryConsumePitonSlot(holder, plan.PitonSlot)) { RollbackFailedReload(cannonItem, shooter, val); HandCannonPlugin.Log.LogWarning((object)"[Reload] piton reload succeeded but piton could not be consumed."); return false; } } else if (!HandCannonInventoryHelper.TryApplyRopePlan(holder, plan.RopePlan)) { RollbackFailedReload(cannonItem, shooter, val); HandCannonPlugin.Log.LogWarning((object)"[Reload] reload succeeded but rope could not be consumed."); return false; } HandCannonStateSync.Sync(cannonItem, shooter); HandCannonNetworkSync.PushAmmoState(cannonItem, val, holder); HandCannonPlugin.Log.LogInfo((object)$"[Reload] ok: loaded {HandCannonAmmoHelper.GetAmmoLabel(plan.AmmoType)}, hasAmmo={HandCannonHelper.HasCharge(cannonItem)}"); return true; } private static void RollbackFailedReload(Item cannonItem, RopeShooter shooter, ItemSlot cannonSlot) { HandCannonAmmoHelper.SetLoadedAmmo(cannonItem, cannonSlot, HandCannonAmmoType.Empty); HandCannonAmmoHelper.ClearUses(cannonItem); HandCannonStateSync.Sync(cannonItem, shooter); } private static bool ApplySlotDataReload(Item cannonItem, RopeShooter shooter, HandCannonAmmoType ammoType, ItemSlot cannonSlot) { if (ammoType == HandCannonAmmoType.AntiRope && cannonItem.itemID != 64 && !AntiRopeCannonReference.IsAvailable()) { HandCannonPlugin.Log.LogWarning((object)"[Reload] anti-grav reload failed: anti reference unavailable."); return false; } int ammo = ((!((Object)(object)shooter != (Object)null)) ? 1 : Mathf.Max(1, shooter.startAmmo)); try { if ((Object)(object)shooter != (Object)null) { ((ItemComponent)shooter).GetData<IntItemData>((DataEntryKey)12, (Func<IntItemData>)(() => ItemDataHelper.CreateIntItemData(ammo))).Value = ammo; } OptionableIntItemData data = cannonItem.GetData<OptionableIntItemData>((DataEntryKey)2); if (data != null) { data.Value = ammo; data.HasData = true; } HandCannonAmmoHelper.SetLoadedAmmo(cannonItem, cannonSlot, ammoType); cannonItem.SetUseRemainingPercentage(1f); VineShooter component = ((Component)cannonItem).GetComponent<VineShooter>(); if ((Object)(object)component != (Object)null && (Object)(object)component.disableOnFire != (Object)null) { component.disableOnFire.SetActive(true); } if ((Object)(object)shooter != (Object)null) { shooter.cantReFire = false; ((ItemComponent)shooter).OnInstanceDataSet(); } cannonItem.finishedCast = false; cannonItem.CancelUsePrimary(); return HandCannonHelper.HasCharge(cannonItem); } catch (Exception ex) { HandCannonPlugin.Log.LogError((object)("[Reload] slot-data failed: " + ex.GetType().Name + ": " + ex.Message)); return false; } } private static void ResetCannonSlotForFreshShot(ItemSlot slot, RopeShooter shooter, HandCannonAmmoType ammoType) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown int value = ((!((Object)(object)shooter != (Object)null)) ? 1 : Mathf.Max(1, shooter.startAmmo)); if (slot.data == null) { slot.data = new ItemInstanceData(Guid.NewGuid()); } ItemDataHelper.SetIntEntry(slot.data, (DataEntryKey)12, value); ItemDataHelper.SetOptionableIntEntry(slot.data, (DataEntryKey)2, value); ItemDataHelper.SetIntEntry(slot.data, HandCannonDataEntryKey.LoadedAmmoType, (int)ammoType); } } internal sealed class HandCannonReloadPickerUI : MonoBehaviour { private const int SortOrder = 3200; private static HandCannonReloadPickerUI _instance; private bool _visible; private bool _built; private List<HandCannonReloadPlan> _openPlans; private Action<HandCannonReloadPlan> _onSelected; private float _openedAt; private CursorLockMode _prevLock; private bool _prevCursorVisible; private RectTransform _panel; private Transform _optionsRoot; private TextMeshProUGUI _help; public static bool IsOpen { get { if ((Object)(object)_instance != (Object)null) { return _instance._visible; } return false; } } public static void TryKeyboardSelect() { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) if (!IsOpen || _instance?._openPlans == null) { return; } for (int i = 0; i < _instance._openPlans.Count && i < 9; i++) { int num = 49 + i; KeyCode val = (KeyCode)(257 + i); if (Input.GetKeyDown((KeyCode)num) || Input.GetKeyDown(val)) { _instance.OnPlanSelected(_instance._openPlans[i]); break; } } } public static void EnsureCreated() { //IL_0013: 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_001e: Expected O, but got Unknown if (!((Object)(object)_instance != (Object)null)) { GameObject val = new GameObject("HandCannonReloadPickerUI"); Object.DontDestroyOnLoad((Object)val); _instance = val.AddComponent<HandCannonReloadPickerUI>(); } } public static void DestroyInstance() { if (!((Object)(object)_instance == (Object)null)) { Object.Destroy((Object)(object)((Component)_instance).gameObject); _instance = null; } } public static void Show(List<HandCannonReloadPlan> plans, Action<HandCannonReloadPlan> onSelected) { EnsureCreated(); _instance.Open(plans, onSelected); } public static void ForceClose() { if (!((Object)(object)_instance == (Object)null)) { _instance.CloseInternal(); } } private void Update() { if (_visible) { Cursor.lockState = (CursorLockMode)0; Cursor.visible = true; if (Time.unscaledTime - _openedAt > 120f) { HandCannonPlugin.Log.LogWarning((object)"[Reload] picker timed out, closing."); CloseInternal(); } } } private void Build() { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Expected O, but got Unknown //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missin