using System; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("Portable Cart Tools")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("CartToolsStandalone")] [assembly: AssemblyTitle("CartToolsStandalone")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace UL.CartToolsStandalone { [BepInPlugin("ul.carttools.standalone", "Portable Cart Tools", "1.0.0")] public sealed class Plugin : BaseUnityPlugin { public const string PluginGuid = "ul.carttools.standalone"; public const string PluginName = "Portable Cart Tools"; public const string PluginVersion = "1.0.0"; internal const bool EnableInventoryIconFixInternal = true; internal const bool ProtectStoredBatteryInternal = true; internal const bool PreventStoredBatteryAnimationInternal = true; internal const bool UseFallbackInventoryIconsInternal = true; internal static ManualLogSource Log; internal static ConfigEntry EnableStandaloneCannon; internal static ConfigEntry EnableStandaloneLaser; internal static ConfigEntry EnableInventoryStorage; internal static ConfigEntry DebugLogging; private Harmony harmony; private void Awake() { //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; EnableStandaloneCannon = ((BaseUnityPlugin)this).Config.Bind("General", "EnableStandaloneCannon", true, "Allow cart cannon items to activate without being inside a cart."); EnableStandaloneLaser = ((BaseUnityPlugin)this).Config.Bind("General", "EnableStandaloneLaser", true, "Allow cart laser items to activate without being inside a cart."); EnableInventoryStorage = ((BaseUnityPlugin)this).Config.Bind("General", "EnableInventoryStorage", true, "Allow cart cannon and cart laser to be stored in player slot inventory. Experimental. Host-only compatibility must be verified."); DebugLogging = ((BaseUnityPlugin)this).Config.Bind("General", "DebugLogging", false, "Enable detailed cart-tool diagnostics for icon assignment, battery guards, and inventory UI refreshes."); harmony = new Harmony("ul.carttools.standalone"); harmony.PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("{0} {1} loaded. StandaloneCannon={2}, StandaloneLaser={3}, InventoryStorage={4}, DebugLogging={5}", "Portable Cart Tools", "1.0.0", EnableStandaloneCannon.Value, EnableStandaloneLaser.Value, EnableInventoryStorage.Value, DebugLogging.Value)); if (EnableInventoryStorage.Value) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Experimental inventory storage uses ItemEquippable on the local item GameObject. Vanilla clients without this mod may not be able to store cart tools because InventorySpot checks GetComponent() locally."); } } private void OnDestroy() { Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } } } [HarmonyPatch(typeof(ItemCartCannonMain), "Start")] internal static class ItemCartCannonMainStartPatch { private static void Postfix(ItemCartCannonMain __instance) { if (Object.op_Implicit((Object)(object)__instance) && StandaloneCartTool.ShouldEnableFor(__instance)) { if (Plugin.EnableInventoryStorage.Value) { CartToolInventoryStorage.TrySetup(__instance); } if (!Object.op_Implicit((Object)(object)((Component)__instance).GetComponent())) { ((Component)__instance).gameObject.AddComponent(); } } } } [HarmonyPatch(typeof(InventorySpot), "EquipItem")] internal static class InventorySpotEquipItemPatch { private static void Prefix(ItemEquippable item) { CartToolInventoryStorage.EnsureIconForEquippable(item, "before inventory equip"); } private static void Postfix(InventorySpot __instance) { if (Object.op_Implicit((Object)(object)__instance) && Object.op_Implicit((Object)(object)__instance.CurrentItem)) { CartToolInventoryStorage.EnsureIconForEquippable(__instance.CurrentItem, "after inventory equip"); __instance.UpdateUI(); } } } [HarmonyPatch(typeof(InventorySpot), "UpdateUI")] internal static class InventorySpotUpdateUIPatch { private static void Prefix(InventorySpot __instance) { if (Object.op_Implicit((Object)(object)__instance) && Object.op_Implicit((Object)(object)__instance.CurrentItem)) { CartToolInventoryStorage.EnsureIconForEquippable(__instance.CurrentItem, "before inventory UI refresh"); } } } [HarmonyPatch(typeof(ItemBattery), "Update")] internal static class ItemBatteryUpdatePatch { private static void Prefix(ItemBattery __instance) { CartToolStoredBatteryGuard.PreventFalseStoredDrain(__instance); } private static void Postfix(ItemBattery __instance) { CartToolStoredBatteryGuard.RestoreAutoDrainIfNeeded(__instance); } } [HarmonyPatch(typeof(ItemBattery), "RemoveFullBar")] internal static class ItemBatteryRemoveFullBarPatch { private static bool Prefix(ItemBattery __instance) { return !CartToolStoredBatteryGuard.ShouldSuppressStoredBatteryRemoval(__instance); } } internal static class CartToolInventoryStorage { private const string CannonIconResource = "UL.CartToolsStandalone.Assets.Icons.cart_cannon_icon.png"; private const string LaserIconResource = "UL.CartToolsStandalone.Assets.Icons.cart_laser_icon.png"; private static readonly FieldInfo ItemAttributesEquippableField = AccessTools.Field(typeof(ItemAttributes), "itemEquippable"); private static readonly FieldInfo ItemBatteryEquippableField = AccessTools.Field(typeof(ItemBattery), "itemEquippable"); private static readonly FieldInfo ItemToggleEquippableField = AccessTools.Field(typeof(ItemToggle), "itemEquippable"); private static readonly FieldInfo ItemAttributesHasIconField = AccessTools.Field(typeof(ItemAttributes), "hasIcon"); private static Sprite customCannonIcon; private static Sprite customLaserIcon; internal static void EnsureIconForEquippable(ItemEquippable itemEquippable, string reason) { if (!Object.op_Implicit((Object)(object)itemEquippable)) { return; } ItemCartCannonMain component = ((Component)itemEquippable).GetComponent(); if (Object.op_Implicit((Object)(object)component)) { bool flag = Object.op_Implicit((Object)(object)((Component)component).GetComponent()); bool flag2 = Object.op_Implicit((Object)(object)((Component)component).GetComponent()); if (flag || flag2) { ConfigureInventoryIcon(component, itemEquippable, flag2 ? "laser" : "cannon", reason); } } } internal static void TrySetup(ItemCartCannonMain cannonMain) { bool flag = Object.op_Implicit((Object)(object)((Component)cannonMain).GetComponent()); bool flag2 = Object.op_Implicit((Object)(object)((Component)cannonMain).GetComponent()); string text = (flag2 ? "laser" : (flag ? "cannon" : "unknown")); if (!flag && !flag2) { return; } PhysGrabObject component = ((Component)cannonMain).GetComponent(); if (!Object.op_Implicit((Object)(object)component)) { Plugin.Log.LogWarning((object)("Inventory storage skipped for " + ((Object)cannonMain).name + ": missing PhysGrabObject.")); return; } ItemEquippable val = ((Component)component).GetComponent(); if (!Object.op_Implicit((Object)(object)val)) { val = ((Component)component).gameObject.AddComponent(); Plugin.Log.LogInfo((object)("Added experimental ItemEquippable to cart " + text + ": " + ((Object)cannonMain).name + ".")); } else { Plugin.Log.LogInfo((object)("Cart " + text + " already has ItemEquippable: " + ((Object)cannonMain).name + ".")); } RefreshCachedEquippable(cannonMain, val); ConfigureInventoryIcon(cannonMain, val, text, "startup"); if (!Object.op_Implicit((Object)(object)((Component)cannonMain).GetComponent())) { ((Component)cannonMain).gameObject.AddComponent(); DebugLog("Enabled cart " + text + " stored battery protection for " + ((Object)cannonMain).name + "."); } StandaloneCartTool component2 = ((Component)cannonMain).GetComponent(); if (Object.op_Implicit((Object)(object)component2)) { component2.EnsureVirtualCart(); } } private static void RefreshCachedEquippable(ItemCartCannonMain cannonMain, ItemEquippable itemEquippable) { SetCachedEquippable((Component)(object)((Component)cannonMain).GetComponent(), ItemAttributesEquippableField, itemEquippable, "ItemAttributes", ((Object)cannonMain).name); SetCachedEquippable((Component)(object)((Component)cannonMain).GetComponent(), ItemBatteryEquippableField, itemEquippable, "ItemBattery", ((Object)cannonMain).name); SetCachedEquippable((Component)(object)((Component)cannonMain).GetComponent(), ItemToggleEquippableField, itemEquippable, "ItemToggle", ((Object)cannonMain).name); } private static void SetCachedEquippable(Component component, FieldInfo field, ItemEquippable itemEquippable, string componentName, string itemName) { if (Object.op_Implicit((Object)(object)component)) { if (field == null) { Plugin.Log.LogWarning((object)("Inventory storage could not refresh " + componentName + " on " + itemName + ": itemEquippable field not found.")); } else { field.SetValue(component, itemEquippable); } } } private static void ConfigureInventoryIcon(ItemCartCannonMain cannonMain, ItemEquippable itemEquippable, string itemType, string reason) { ItemAttributes component = ((Component)itemEquippable).GetComponent(); if (!Object.op_Implicit((Object)(object)component)) { component = ((Component)cannonMain).GetComponent(); } DebugLog("Inventory icon diagnostics (" + reason + ") for cart " + itemType + ": item=" + ((Object)cannonMain).name + ", equippableGO=" + ((Object)((Component)itemEquippable).gameObject).name + ", attributesGO=" + (Object.op_Implicit((Object)(object)component) ? ((Object)((Component)component).gameObject).name : "missing") + ", iconBefore=" + ((Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component.icon)) ? "set" : "null") + "."); if (!Object.op_Implicit((Object)(object)component)) { Plugin.Log.LogWarning((object)("Inventory icon setup skipped for " + ((Object)cannonMain).name + ": missing ItemAttributes.")); return; } Sprite customIcon = GetCustomIcon(itemType == "laser"); if (Object.op_Implicit((Object)(object)customIcon)) { string text = (Object.op_Implicit((Object)(object)component.icon) ? ((Object)component.icon).name : "null"); component.icon = customIcon; itemEquippable.ItemIcon = customIcon; MarkHasIcon(component, ((Object)cannonMain).name); DebugLog("Inventory icon assigned custom PNG for cart " + itemType + ": " + ((Object)cannonMain).name + ". attributesGO=" + ((Object)((Component)component).gameObject).name + ", before=" + text + ", after=" + (Object.op_Implicit((Object)(object)component.icon) ? ((Object)component.icon).name : "null") + ", fallbackUsed=False."); return; } if (Object.op_Implicit((Object)(object)component.icon) && IsCustomIcon(component.icon)) { itemEquippable.ItemIcon = component.icon; MarkHasIcon(component, ((Object)cannonMain).name); DebugLog("Inventory icon already has custom PNG for cart " + itemType + ": " + ((Object)cannonMain).name + "."); return; } if (Object.op_Implicit((Object)(object)component.icon)) { itemEquippable.ItemIcon = component.icon; MarkHasIcon(component, ((Object)cannonMain).name); DebugLog("Inventory icon reused from ItemAttributes for cart " + itemType + ": " + ((Object)cannonMain).name + "."); return; } SemiIconMaker componentInChildren = ((Component)cannonMain).GetComponentInChildren(true); if (Object.op_Implicit((Object)(object)componentInChildren)) { Sprite val = componentInChildren.CreateIconFromRenderTexture(((Object)((Component)cannonMain).gameObject).name.Replace("(Clone)", string.Empty).ToLowerInvariant()); if (Object.op_Implicit((Object)(object)val)) { component.icon = val; itemEquippable.ItemIcon = val; MarkHasIcon(component, ((Object)cannonMain).name); DebugLog("Inventory icon generated for cart " + itemType + ": " + ((Object)cannonMain).name + "."); return; } } Sprite val2 = FindFallbackSprite((Component)(object)cannonMain); if (!Object.op_Implicit((Object)(object)val2)) { val2 = CreateFallbackIcon(itemType == "laser"); } if (Object.op_Implicit((Object)(object)val2)) { component.icon = val2; itemEquippable.ItemIcon = val2; MarkHasIcon(component, ((Object)cannonMain).name); Plugin.Log.LogWarning((object)("Inventory icon used fallback sprite for cart " + itemType + ": " + ((Object)cannonMain).name + ".")); } else { Plugin.Log.LogWarning((object)("Inventory icon setup found no icon source for cart " + itemType + ": " + ((Object)cannonMain).name + ". Slot icon may remain blank.")); } } private static Sprite GetCustomIcon(bool isLaser) { if (isLaser) { if (customLaserIcon == null) { customLaserIcon = LoadEmbeddedIcon("UL.CartToolsStandalone.Assets.Icons.cart_laser_icon.png", "cart laser"); } return customLaserIcon; } if (customCannonIcon == null) { customCannonIcon = LoadEmbeddedIcon("UL.CartToolsStandalone.Assets.Icons.cart_cannon_icon.png", "cart cannon"); } return customCannonIcon; } private static Sprite LoadEmbeddedIcon(string resourceName, string label) { //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Expected O, but got Unknown //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName); if (stream == null) { Plugin.Log.LogWarning((object)("Custom inventory icon resource missing for " + label + ": " + resourceName + ".")); return null; } byte[] array = new byte[stream.Length]; int num; for (int i = 0; i < array.Length; i += num) { num = stream.Read(array, i, array.Length - i); if (num <= 0) { break; } } DebugLog($"Custom inventory icon stream found for {label}: {resourceName}, length={array.Length}."); Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); bool flag = ImageConversion.LoadImage(val, array, false); DebugLog($"Custom inventory icon texture load for {label}: loaded={flag}, bytes={array.Length}, size={((Texture)val).width}x{((Texture)val).height}."); if (!flag) { Plugin.Log.LogWarning((object)("Custom inventory icon failed to decode for " + label + ": " + resourceName + ".")); return null; } ((Object)val).name = resourceName; Sprite val2 = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), (float)Mathf.Max(((Texture)val).width, ((Texture)val).height)); if (!Object.op_Implicit((Object)(object)val2)) { Plugin.Log.LogWarning((object)("Custom inventory icon sprite creation failed for " + label + ": " + resourceName + ".")); return null; } ((Object)val2).name = resourceName; Plugin.Log.LogInfo((object)$"Loaded custom inventory icon for {label}: {resourceName} ({((Texture)val).width}x{((Texture)val).height})."); return val2; } private static bool IsCustomIcon(Sprite sprite) { if (Object.op_Implicit((Object)(object)sprite)) { if (!(((Object)sprite).name == "UL.CartToolsStandalone.Assets.Icons.cart_cannon_icon.png")) { return ((Object)sprite).name == "UL.CartToolsStandalone.Assets.Icons.cart_laser_icon.png"; } return true; } return false; } private static Sprite FindFallbackSprite(Component root) { SpriteRenderer componentInChildren = root.GetComponentInChildren(true); if (Object.op_Implicit((Object)(object)componentInChildren) && Object.op_Implicit((Object)(object)componentInChildren.sprite)) { return componentInChildren.sprite; } return null; } private static Sprite CreateFallbackIcon(bool isLaser) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_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_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false); Color val2 = default(Color); ((Color)(ref val2))..ctor(0f, 0f, 0f, 0f); Color color = (isLaser ? new Color(0.2f, 0.85f, 1f, 1f) : new Color(1f, 0.45f, 0.12f, 1f)); Color white = Color.white; for (int i = 0; i < 64; i++) { for (int j = 0; j < 64; j++) { val.SetPixel(j, i, val2); } } DrawRect(val, 10, 28, 44, 10, color); DrawRect(val, 44, 23, 10, 20, color); DrawRect(val, 16, 24, 12, 18, color); DrawRect(val, 48, 30, 8, 6, white); DrawRect(val, isLaser ? 55 : 6, 31, 8, 4, color); val.Apply(); return Sprite.Create(val, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f), 64f); } private static void DrawRect(Texture2D texture, int x, int y, int width, int height, Color color) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) for (int i = y; i < y + height; i++) { for (int j = x; j < x + width; j++) { if (j >= 0 && j < ((Texture)texture).width && i >= 0 && i < ((Texture)texture).height) { texture.SetPixel(j, i, color); } } } } private static void MarkHasIcon(ItemAttributes attributes, string itemName) { if (ItemAttributesHasIconField == null) { Plugin.Log.LogWarning((object)("Inventory icon setup could not mark hasIcon on " + itemName + ": hasIcon field not found.")); } else { ItemAttributesHasIconField.SetValue(attributes, true); } } private static void DebugLog(string message) { if (Plugin.DebugLogging.Value) { Plugin.Log.LogInfo((object)message); } } } internal sealed class CartToolStoredBatteryGuard : MonoBehaviour { private static readonly FieldInfo ItemEquippableIsEquippedField = AccessTools.Field(typeof(ItemEquippable), "isEquipped"); private static readonly FieldInfo ItemEquippableIsEquippingField = AccessTools.Field(typeof(ItemEquippable), "isEquipping"); private static readonly FieldInfo ItemEquippableEquippedSpotField = AccessTools.Field(typeof(ItemEquippable), "equippedSpot"); private static readonly FieldInfo ItemBatteryLifeIntField = AccessTools.Field(typeof(ItemBattery), "batteryLifeInt"); private static readonly FieldInfo ItemBatteryVisualLogicField = AccessTools.Field(typeof(ItemBattery), "batteryVisualLogic"); private static ItemBattery autoDrainSuppressedBattery; private static bool autoDrainSuppressedPreviousValue; private ItemCartCannonMain cannonMain; private ItemBattery battery; private ItemEquippable itemEquippable; private string itemType; private float storedBatteryLife; private int storedBatteryLifeInt; private bool hasStoredSnapshot; private bool loggedProtectionActive; internal static void PreventFalseStoredDrain(ItemBattery itemBattery) { if (!Object.op_Implicit((Object)(object)itemBattery)) { return; } CartToolStoredBatteryGuard component = ((Component)itemBattery).GetComponent(); if (Object.op_Implicit((Object)(object)component) && component.IsStored()) { autoDrainSuppressedBattery = itemBattery; autoDrainSuppressedPreviousValue = itemBattery.autoDrain; if (itemBattery.autoDrain) { itemBattery.autoDrain = false; component.RefreshSnapshotIfNeeded(); } } } internal static bool ShouldSuppressStoredBatteryRemoval(ItemBattery itemBattery) { if (!Object.op_Implicit((Object)(object)itemBattery)) { return false; } CartToolStoredBatteryGuard component = ((Component)itemBattery).GetComponent(); if (!Object.op_Implicit((Object)(object)component) || !component.IsStoredOrEquipping()) { return false; } component.RefreshSnapshotIfNeeded(); component.RestoreSnapshotAndVisuals(); if (Plugin.DebugLogging.Value) { Plugin.Log.LogInfo((object)("Suppressed stored cart " + component.itemType + " battery bar removal for " + ((Object)component).name + ".")); } return true; } internal static void RestoreAutoDrainIfNeeded(ItemBattery itemBattery) { if (!((Object)(object)autoDrainSuppressedBattery != (Object)(object)itemBattery)) { itemBattery.autoDrain = autoDrainSuppressedPreviousValue; autoDrainSuppressedBattery = null; } } private void Awake() { cannonMain = ((Component)this).GetComponent(); battery = ((Component)this).GetComponent(); itemEquippable = ((Component)this).GetComponent(); itemType = (Object.op_Implicit((Object)(object)((Component)this).GetComponent()) ? "laser" : "cannon"); if (ItemEquippableIsEquippedField == null) { Plugin.Log.LogWarning((object)("Cart tool battery guard missing reflection field: ItemEquippable.isEquipped on " + ((Object)this).name + ".")); } if (ItemEquippableIsEquippingField == null) { Plugin.Log.LogWarning((object)("Cart tool battery guard missing reflection field: ItemEquippable.isEquipping on " + ((Object)this).name + ".")); } if (ItemEquippableEquippedSpotField == null) { Plugin.Log.LogWarning((object)("Cart tool battery guard missing reflection field: ItemEquippable.equippedSpot on " + ((Object)this).name + ".")); } if (ItemBatteryLifeIntField == null) { Plugin.Log.LogWarning((object)("Cart tool battery guard missing reflection field: ItemBattery.batteryLifeInt on " + ((Object)this).name + ".")); } if (ItemBatteryVisualLogicField == null) { Plugin.Log.LogWarning((object)("Cart tool battery guard missing reflection field: ItemBattery.batteryVisualLogic on " + ((Object)this).name + ".")); } } private void LateUpdate() { if (!Object.op_Implicit((Object)(object)cannonMain) || !Object.op_Implicit((Object)(object)battery)) { return; } if (!Object.op_Implicit((Object)(object)itemEquippable)) { itemEquippable = ((Component)this).GetComponent(); } if (!IsStored()) { hasStoredSnapshot = false; return; } RefreshSnapshotIfNeeded(); int batteryLifeInt = GetBatteryLifeInt(battery); if (battery.batteryLife < storedBatteryLife || batteryLifeInt < storedBatteryLifeInt) { RestoreSnapshotAndVisuals(); return; } storedBatteryLife = battery.batteryLife; storedBatteryLifeInt = batteryLifeInt; } private static bool IsEquipped(ItemEquippable itemEquippable) { if (ItemEquippableIsEquippedField == null) { return false; } return (bool)ItemEquippableIsEquippedField.GetValue(itemEquippable); } private static bool IsEquipping(ItemEquippable itemEquippable) { if (ItemEquippableIsEquippingField == null) { return false; } return (bool)ItemEquippableIsEquippingField.GetValue(itemEquippable); } private static bool HasEquippedSpot(ItemEquippable itemEquippable) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown if (ItemEquippableEquippedSpotField == null) { return false; } return Object.op_Implicit((Object)(InventorySpot)ItemEquippableEquippedSpotField.GetValue(itemEquippable)); } private bool IsStored() { if (!Object.op_Implicit((Object)(object)itemEquippable)) { itemEquippable = ((Component)this).GetComponent(); } if (Object.op_Implicit((Object)(object)itemEquippable)) { return IsEquipped(itemEquippable); } return false; } private bool IsStoredOrEquipping() { if (!Object.op_Implicit((Object)(object)itemEquippable)) { itemEquippable = ((Component)this).GetComponent(); } if (Object.op_Implicit((Object)(object)itemEquippable)) { if (!IsEquipped(itemEquippable) && !IsEquipping(itemEquippable)) { return HasEquippedSpot(itemEquippable); } return true; } return false; } private void RefreshSnapshotIfNeeded() { if (hasStoredSnapshot) { return; } storedBatteryLife = battery.batteryLife; storedBatteryLifeInt = GetBatteryLifeInt(battery); hasStoredSnapshot = true; if (!loggedProtectionActive) { loggedProtectionActive = true; if (Plugin.DebugLogging.Value) { Plugin.Log.LogInfo((object)$"Cart {itemType} storage battery protection active for {((Object)this).name}: preserving {storedBatteryLifeInt} bars."); } } } private void RestoreSnapshotAndVisuals() { battery.batteryLife = storedBatteryLife; SetBatteryLifeInt(battery, storedBatteryLifeInt); BatteryVisualLogic batteryVisualLogic = GetBatteryVisualLogic(battery); if (Object.op_Implicit((Object)(object)batteryVisualLogic)) { batteryVisualLogic.BatteryBarsUpdate(storedBatteryLifeInt, true); } } private static int GetBatteryLifeInt(ItemBattery itemBattery) { if (ItemBatteryLifeIntField == null) { return Mathf.RoundToInt(itemBattery.batteryLife); } return (int)ItemBatteryLifeIntField.GetValue(itemBattery); } private static void SetBatteryLifeInt(ItemBattery itemBattery, int value) { if (ItemBatteryLifeIntField != null) { ItemBatteryLifeIntField.SetValue(itemBattery, value); } } private static BatteryVisualLogic GetBatteryVisualLogic(ItemBattery itemBattery) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown if (ItemBatteryVisualLogicField == null) { return null; } return (BatteryVisualLogic)ItemBatteryVisualLogicField.GetValue(itemBattery); } } internal sealed class StandaloneCartTool : MonoBehaviour { private static readonly FieldInfo ImpactDetectorField = AccessTools.Field(typeof(ItemCartCannonMain), "impactDetector"); private static readonly FieldInfo CurrentCartField = AccessTools.Field(typeof(PhysGrabObjectImpactDetector), "currentCart"); private static readonly FieldInfo TimerInCartField = AccessTools.Field(typeof(PhysGrabObjectImpactDetector), "timerInCart"); private ItemCartCannonMain cannonMain; private PhysGrabObjectImpactDetector impactDetector; private GameObject virtualCartObject; private PhysGrabCart virtualCart; private bool applyingVirtualCart; internal static bool ShouldEnableFor(ItemCartCannonMain cannonMain) { bool num = Object.op_Implicit((Object)(object)((Component)cannonMain).GetComponent()); bool flag = Object.op_Implicit((Object)(object)((Component)cannonMain).GetComponent()); if (num && Plugin.EnableStandaloneCannon.Value) { return true; } if (flag && Plugin.EnableStandaloneLaser.Value) { return true; } return false; } private void Awake() { cannonMain = ((Component)this).GetComponent(); } private void Start() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown impactDetector = (PhysGrabObjectImpactDetector)ImpactDetectorField.GetValue(cannonMain); if (!Object.op_Implicit((Object)(object)impactDetector)) { Plugin.Log.LogWarning((object)("Standalone setup skipped for " + ((Object)this).name + ": missing PhysGrabObjectImpactDetector.")); ((Behaviour)this).enabled = false; } else { CreateVirtualCart(); } } private void LateUpdate() { ApplyVirtualCartIfNeeded(); } private void FixedUpdate() { ApplyVirtualCartIfNeeded(); } private void OnDestroy() { if (Object.op_Implicit((Object)(object)virtualCartObject)) { Object.Destroy((Object)(object)virtualCartObject); } } private void CreateVirtualCart() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown //IL_003d: 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_0067: Unknown result type (might be due to invalid IL or missing references) virtualCartObject = new GameObject(((Object)this).name + " Standalone Cart Anchor"); virtualCartObject.transform.SetParent(((Component)this).transform, false); virtualCartObject.transform.localPosition = Vector3.zero; virtualCartObject.transform.localRotation = Quaternion.identity; virtualCartObject.transform.localScale = Vector3.one; virtualCart = virtualCartObject.AddComponent(); ((Behaviour)virtualCart).enabled = false; } private void ApplyVirtualCartIfNeeded() { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Expected O, but got Unknown if (applyingVirtualCart || !Object.op_Implicit((Object)(object)impactDetector) || !Object.op_Implicit((Object)(object)virtualCart)) { if (Object.op_Implicit((Object)(object)impactDetector) && !Object.op_Implicit((Object)(object)virtualCart)) { EnsureVirtualCart(); } } else if (ShouldEnableFor(cannonMain)) { PhysGrabCart val = (PhysGrabCart)CurrentCartField.GetValue(impactDetector); if (!Object.op_Implicit((Object)(object)val) || !((Object)(object)val != (Object)(object)virtualCart)) { applyingVirtualCart = true; CurrentCartField.SetValue(impactDetector, virtualCart); TimerInCartField.SetValue(impactDetector, 0.2f); impactDetector.inCart = true; applyingVirtualCart = false; } } } internal void EnsureVirtualCart() { if (Object.op_Implicit((Object)(object)virtualCart)) { return; } if (Object.op_Implicit((Object)(object)virtualCartObject)) { virtualCart = virtualCartObject.GetComponent(); if (Object.op_Implicit((Object)(object)virtualCart)) { ((Behaviour)virtualCart).enabled = false; return; } } CreateVirtualCart(); Plugin.Log.LogInfo((object)("Recreated standalone cart anchor for " + ((Object)this).name + ".")); } } }