Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of ShoppingCart v1.0.3
ShoppingCart.dll
Decompiled 3 months agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using ExitGames.Client.Photon; using HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using Photon.Realtime; using ShoppingCart; using TMPro; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: IgnoresAccessChecksTo("")] [assembly: AssemblyCompany("Tolga")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.2.0")] [assembly: AssemblyInformationalVersion("1.0.2")] [assembly: AssemblyProduct("ShoppingCart")] [assembly: AssemblyTitle("ShoppingCart")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.2.0")] [module: UnverifiableCode] [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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [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; } } } public class ShopCartComponent : MonoBehaviour { private List<ItemAttributes> itemsInCart = new List<ItemAttributes>(); private Transform? inCartTransform; private Collider? inCartTrigger; private float rescanTimer; private const float RESCAN_INTERVAL = 0.2f; private float nextValueDebugLogTime; private string? lastSetDisplayText; private float lastSetDisplayTime; private static FieldInfo? ShopItemField; private int totalCost; public TextMeshPro? costDisplay; private PhotonView? photonView; private PhysGrabObject? physGrabObject; private MeshRenderer? cartMesh; private float cleanupTimer; private const float CLEANUP_INTERVAL = 0.5f; private void Awake() { photonView = ((Component)this).GetComponent<PhotonView>(); physGrabObject = ((Component)this).GetComponent<PhysGrabObject>(); inCartTransform = ((Component)this).transform.Find("In Cart"); if ((Object)(object)inCartTransform != (Object)null) { inCartTrigger = ((Component)inCartTransform).GetComponent<Collider>(); if ((Object)(object)inCartTrigger == (Object)null) { global::ShoppingCart.ShoppingCart.LogWarning("ShopCartComponent: 'In Cart' child has no Collider!"); } else if (!inCartTrigger.isTrigger) { global::ShoppingCart.ShoppingCart.LogWarning("ShopCartComponent: 'In Cart' collider is not marked as Trigger. Value scanning will still work, but trigger events won't."); } if ((Object)(object)((Component)inCartTransform).GetComponent<ShopCartTrigger>() == (Object)null) { global::ShoppingCart.ShoppingCart.LogWarning("ShopCartComponent: 'In Cart' child needs ShopCartTrigger component!"); } } else { global::ShoppingCart.ShoppingCart.LogWarning("ShopCartComponent: 'In Cart' child GameObject not found!"); } if ((Object)(object)costDisplay == (Object)null) { Transform val = ((Component)this).transform.Find("Screen/Text"); if ((Object)(object)val != (Object)null) { costDisplay = ((Component)val).GetComponent<TextMeshPro>(); } if ((Object)(object)costDisplay == (Object)null) { TextMeshPro[] componentsInChildren = ((Component)this).GetComponentsInChildren<TextMeshPro>(true); costDisplay = ((IEnumerable<TextMeshPro>)componentsInChildren).FirstOrDefault((Func<TextMeshPro, bool>)((TextMeshPro t) => (Object)(object)t.transform.parent != (Object)null && ((Object)t.transform.parent).name == "Screen" && ((Object)t).name == "Text")) ?? ((IEnumerable<TextMeshPro>)componentsInChildren).FirstOrDefault((Func<TextMeshPro, bool>)((TextMeshPro t) => ((Object)t).name.Contains("Screen") || ((Object)(object)t.transform.parent != (Object)null && ((Object)t.transform.parent).name.Contains("Screen")))) ?? componentsInChildren.FirstOrDefault(); } } cartMesh = ((IEnumerable<MeshRenderer>)((Component)this).GetComponentsInChildren<MeshRenderer>(true)).FirstOrDefault((Func<MeshRenderer, bool>)((MeshRenderer m) => (Object)(object)((Component)m).transform != (Object)(object)((Component)this).transform)); } private void Start() { try { CartMaterialRepair.RepairCartMaterials(((Component)this).gameObject); } catch { } UpdateCostDisplay(); if (global::ShoppingCart.ShoppingCart.CartValueDebugLogging.Value) { global::ShoppingCart.ShoppingCart.LogInfo("ShopCartComponent: Start on '" + ((Object)((Component)this).gameObject).name + "'. costDisplay=" + (((Object)(object)costDisplay != (Object)null) ? ((Object)costDisplay).name : "<null>") + ", inCartTrigger=" + (((Object)(object)inCartTrigger != (Object)null) ? ((object)inCartTrigger).GetType().Name : "<null>")); } } private void Update() { if (SemiFunc.RunIsShop() && SemiFunc.IsMasterClientOrSingleplayer()) { if (global::ShoppingCart.ShoppingCart.CartValueDebugLogging.Value && (Object)(object)costDisplay != (Object)null && lastSetDisplayText != null && Time.unscaledTime - lastSetDisplayTime < 1f && ((TMP_Text)costDisplay).text != lastSetDisplayText) { global::ShoppingCart.ShoppingCart.LogWarning("ShopCartComponent: Screen text overwritten. Expected '" + lastSetDisplayText + "', actual '" + ((TMP_Text)costDisplay).text + "'. Another script is writing to the same TMP."); lastSetDisplayTime = -999f; } rescanTimer -= Time.deltaTime; if (rescanTimer <= 0f) { RescanAndRecalculate(); rescanTimer = 0.2f; } cleanupTimer -= Time.deltaTime; if (cleanupTimer <= 0f) { CleanupDestroyedItems(); cleanupTimer = 0.5f; } } } public void OnItemEnter(ItemAttributes itemAttributes) { if (SemiFunc.IsMasterClientOrSingleplayer() && SemiFunc.RunIsShop()) { RescanAndRecalculate(); } } public void OnItemExit(ItemAttributes itemAttributes) { if (SemiFunc.IsMasterClientOrSingleplayer() && SemiFunc.RunIsShop()) { RescanAndRecalculate(); } } private bool IsPurchasableShopItem(ItemAttributes itemAttributes) { if ((Object)(object)itemAttributes == (Object)null) { return false; } if (!SemiFunc.RunIsShop()) { return false; } if ((object)ShopItemField == null) { ShopItemField = typeof(ItemAttributes).GetField("shopItem", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } if (ShopItemField != null && ShopItemField.FieldType == typeof(bool)) { try { return (bool)ShopItemField.GetValue(itemAttributes); } catch { } } return (Object)(object)itemAttributes.item != (Object)null; } private void RescanAndRecalculate() { //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: 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_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_02a9: Unknown result type (might be due to invalid IL or missing references) //IL_02b2: Unknown result type (might be due to invalid IL or missing references) //IL_02bd: Unknown result type (might be due to invalid IL or missing references) //IL_025d: Unknown result type (might be due to invalid IL or missing references) if (!SemiFunc.IsMasterClientOrSingleplayer()) { return; } if ((Object)(object)inCartTransform == (Object)null || (Object)(object)inCartTrigger == (Object)null) { if (global::ShoppingCart.ShoppingCart.CartValueDebugLogging.Value && Time.unscaledTime >= nextValueDebugLogTime) { global::ShoppingCart.ShoppingCart.LogWarning($"ShopCartComponent: Missing inCartTransform/inCartTrigger. inCartTransform={(Object)(object)inCartTransform != (Object)null}, inCartTrigger={(Object)(object)inCartTrigger != (Object)null}"); nextValueDebugLogTime = Time.unscaledTime + 1f; } return; } Collider? obj = inCartTrigger; BoxCollider val = (BoxCollider)(object)((obj is BoxCollider) ? obj : null); Vector3 val2; Vector3 val3; Quaternion val4; if (val != null) { val2 = ((Component)val).transform.TransformPoint(val.center); Vector3 lossyScale = ((Component)val).transform.lossyScale; ((Vector3)(ref lossyScale))..ctor(Mathf.Abs(lossyScale.x), Mathf.Abs(lossyScale.y), Mathf.Abs(lossyScale.z)); val3 = Vector3.Scale(val.size * 0.5f, lossyScale); val4 = ((Component)val).transform.rotation; } else { Bounds bounds = inCartTrigger.bounds; val2 = ((Bounds)(ref bounds)).center; val3 = ((Bounds)(ref bounds)).extents; val4 = Quaternion.identity; } Collider[] array = Physics.OverlapBox(val2, val3, val4, -1, (QueryTriggerInteraction)1); if (array == null) { return; } itemsInCart.Clear(); int num = 0; int num2 = 0; Collider[] array2 = array; foreach (Collider val5 in array2) { if ((Object)(object)val5 == (Object)null || ((Component)val5).transform.IsChildOf(((Component)this).transform)) { continue; } ItemAttributes componentInParent = ((Component)val5).GetComponentInParent<ItemAttributes>(); if ((Object)(object)componentInParent == (Object)null || !IsPurchasableShopItem(componentInParent) || itemsInCart.Contains(componentInParent)) { continue; } itemsInCart.Add(componentInParent); num += componentInParent.value; num2++; if (global::ShoppingCart.ShoppingCart.CartValueDebugLogging.Value && Time.unscaledTime >= nextValueDebugLogTime) { bool flag = IsPurchasableShopItem(componentInParent); int num3 = 0; PhotonView component = ((Component)componentInParent).GetComponent<PhotonView>(); if ((Object)(object)component != (Object)null) { num3 = component.ViewID; } global::ShoppingCart.ShoppingCart.LogInfo($"ShopCartComponent: Found item '{((Object)((Component)componentInParent).gameObject).name}' value={componentInParent.value} shopItem={flag} pv={num3} at {((Component)componentInParent).transform.position}"); } } if (global::ShoppingCart.ShoppingCart.CartValueDebugLogging.Value && Time.unscaledTime >= nextValueDebugLogTime) { global::ShoppingCart.ShoppingCart.LogInfo($"ShopCartComponent: OverlapBox center={val2} ext={val3} rotY={((Quaternion)(ref val4)).eulerAngles.y:F1} overlaps={array.Length} uniqueItems={num2} newTotal={num}"); nextValueDebugLogTime = Time.unscaledTime + 1f; } if (num != totalCost) { totalCost = num; UpdateCostDisplay(); if (SemiFunc.IsMultiplayer() && (Object)(object)photonView != (Object)null) { photonView.RPC("UpdateCartDisplayRPC", (RpcTarget)1, new object[1] { totalCost }); } } } private void CalculateTotalCost() { if (!SemiFunc.IsMasterClientOrSingleplayer()) { return; } int num = 0; foreach (ItemAttributes item in itemsInCart) { if ((Object)(object)item != (Object)null) { num += item.value; } } if (num != totalCost) { totalCost = num; UpdateCostDisplay(); if (SemiFunc.IsMultiplayer() && (Object)(object)photonView != (Object)null) { photonView.RPC("UpdateCartDisplayRPC", (RpcTarget)1, new object[1] { totalCost }); } } } private void UpdateCostDisplay() { if ((Object)(object)costDisplay == (Object)null) { if (global::ShoppingCart.ShoppingCart.CartValueDebugLogging.Value && Time.unscaledTime >= nextValueDebugLogTime) { global::ShoppingCart.ShoppingCart.LogWarning("ShopCartComponent: costDisplay is null; cannot update screen text."); nextValueDebugLogTime = Time.unscaledTime + 1f; } return; } string text = SemiFunc.DollarGetString(Mathf.Max(0, totalCost)); string text2 = "$" + text; ((TMP_Text)costDisplay).text = text2; ((Component)costDisplay).gameObject.SetActive(true); lastSetDisplayText = text2; lastSetDisplayTime = Time.unscaledTime; if (global::ShoppingCart.ShoppingCart.CartValueDebugLogging.Value && Time.unscaledTime >= nextValueDebugLogTime) { global::ShoppingCart.ShoppingCart.LogInfo("ShopCartComponent: Set screen text to '" + text2 + "' on '" + ((Object)costDisplay).name + "'"); nextValueDebugLogTime = Time.unscaledTime + 1f; } } [PunRPC] private void UpdateCartDisplayRPC(int syncedTotalCost, PhotonMessageInfo info = default(PhotonMessageInfo)) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) if (SemiFunc.MasterOnlyRPC(info)) { totalCost = syncedTotalCost; UpdateCostDisplay(); } } private void CleanupDestroyedItems() { if (!SemiFunc.IsMasterClientOrSingleplayer()) { return; } bool flag = false; for (int num = itemsInCart.Count - 1; num >= 0; num--) { if ((Object)(object)itemsInCart[num] == (Object)null || (Object)(object)((Component)itemsInCart[num]).gameObject == (Object)null) { itemsInCart.RemoveAt(num); flag = true; } } if (flag) { CalculateTotalCost(); } } } public class ShopCartTrigger : MonoBehaviour { public ShopCartComponent? parentCart; private static readonly int[] ALLOWED_ITEM_LAYERS = new int[4] { 9, 16, 20, 23 }; private void Awake() { parentCart = ((Component)this).GetComponentInParent<ShopCartComponent>(); if ((Object)(object)parentCart == (Object)null) { Debug.LogError((object)"ShopCartTrigger: Parent ShopCartComponent not found!"); } else { Debug.Log((object)("ShopCartTrigger: Found parent cart at '" + ((Object)((Component)parentCart).gameObject).name + "'")); } } private void OnTriggerEnter(Collider other) { if ((Object)(object)parentCart == (Object)null || (Object)(object)((Component)other).transform.root == (Object)(object)((Component)this).transform.root) { return; } int otherLayer = ((Component)other).gameObject.layer; if (Array.Exists(ALLOWED_ITEM_LAYERS, (int layer) => layer == otherLayer)) { ItemAttributes componentInParent = ((Component)other).GetComponentInParent<ItemAttributes>(); if ((Object)(object)componentInParent != (Object)null) { parentCart.OnItemEnter(componentInParent); } } } private void OnTriggerExit(Collider other) { if ((Object)(object)parentCart == (Object)null) { return; } int otherLayer = ((Component)other).gameObject.layer; if (Array.Exists(ALLOWED_ITEM_LAYERS, (int layer) => layer == otherLayer)) { ItemAttributes componentInParent = ((Component)other).GetComponentInParent<ItemAttributes>(); if ((Object)(object)componentInParent != (Object)null) { parentCart.OnItemExit(componentInParent); } } } } namespace ShoppingCart { internal static class CartMaterialRepair { internal static void RepairCartMaterials(GameObject cartRoot) { if ((Object)(object)cartRoot == (Object)null) { return; } Renderer[] componentsInChildren; try { componentsInChildren = cartRoot.GetComponentsInChildren<Renderer>(true); } catch { return; } foreach (Renderer val in componentsInChildren) { if ((Object)(object)val == (Object)null) { continue; } Material[] materials; try { materials = val.materials; } catch { continue; } bool flag = IsBasketLike(((Object)((Component)val).gameObject).name); foreach (Material val2 in materials) { if (!((Object)(object)val2 == (Object)null)) { if (IsBrokenOrErrorShader(val2)) { TryRepairMaterialShader(val2, flag); } else if (flag) { TryEnableAlphaClip(val2); } } } try { val.materials = materials; } catch { } } } private static bool IsBasketLike(string name) { if (string.IsNullOrEmpty(name)) { return false; } string text = name.ToLowerInvariant(); if (!text.Contains("basket") && !text.Contains("wire") && !text.Contains("grid") && !text.Contains("net") && !text.Contains("mesh")) { return text.Contains("cage"); } return true; } private static bool IsBrokenOrErrorShader(Material mat) { Shader shader = mat.shader; if ((Object)(object)shader == (Object)null) { return true; } string text = ((Object)shader).name ?? string.Empty; if (text.Contains("InternalErrorShader", StringComparison.OrdinalIgnoreCase)) { return true; } if (text.Contains("Hidden/InternalErrorShader", StringComparison.OrdinalIgnoreCase)) { return true; } return false; } private static void TryRepairMaterialShader(Material mat, bool basketLike) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0071: 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) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) Texture val = null; if (mat.HasProperty("_BaseMap")) { val = mat.GetTexture("_BaseMap"); } if ((Object)(object)val == (Object)null && mat.HasProperty("_MainTex")) { val = mat.GetTexture("_MainTex"); } Color val2 = Color.white; if (mat.HasProperty("_BaseColor")) { val2 = mat.GetColor("_BaseColor"); } else if (mat.HasProperty("_Color")) { val2 = mat.GetColor("_Color"); } Shader val3 = Shader.Find("Universal Render Pipeline/Lit"); if ((Object)(object)val3 == (Object)null) { val3 = Shader.Find("Standard"); } if ((Object)(object)val3 == (Object)null) { return; } mat.shader = val3; if (mat.HasProperty("_BaseColor")) { mat.SetColor("_BaseColor", val2); } if (mat.HasProperty("_Color")) { mat.SetColor("_Color", val2); } if ((Object)(object)val != (Object)null) { if (mat.HasProperty("_BaseMap")) { mat.SetTexture("_BaseMap", val); } if (mat.HasProperty("_MainTex")) { mat.SetTexture("_MainTex", val); } } if (basketLike) { TryEnableAlphaClip(mat); } } private static void TryEnableAlphaClip(Material mat) { if (mat.HasProperty("_AlphaClip")) { mat.SetFloat("_AlphaClip", 1f); } if (mat.HasProperty("_Cutoff")) { float num = mat.GetFloat("_Cutoff"); if (num <= 0f) { num = 0.5f; } mat.SetFloat("_Cutoff", num); } try { mat.EnableKeyword("_ALPHATEST_ON"); } catch { } } } [HarmonyPatch(typeof(PlayerController))] internal static class ExamplePlayerControllerPatch { [HarmonyPrefix] [HarmonyPatch("Start")] private static void Start_Prefix(PlayerController __instance) { ShoppingCart.Logger.LogDebug((object)$"{__instance} Start Prefix"); } [HarmonyPostfix] [HarmonyPatch("Start")] private static void Start_Postfix(PlayerController __instance) { ShoppingCart.Logger.LogDebug((object)$"{__instance} Start Postfix"); } } [HarmonyPatch(typeof(ItemAttributes), "ShowInfo")] internal static class ItemAttributesShowInfoPatch { [HarmonyPrefix] private static bool Prefix(ItemAttributes __instance) { if ((Object)(object)__instance == (Object)null) { return false; } int spawnedCartInstanceID = ShopCartSpawner.SpawnedCartInstanceID; if (spawnedCartInstanceID != 0 && ((Object)((Component)__instance).gameObject).GetInstanceID() == spawnedCartInstanceID) { return false; } return true; } } [HarmonyPatch(typeof(PhysGrabCart), "CartSteer")] internal static class PhysGrabCartDistancePatch { private static float _nextCartSteerLogTime; private static float _lastA; private static float _lastB; private static float _lastD; private static float _lastTurnMultiplier; private static float _lastTurnMinFactor; private static float _lastTurnMaxClamp; [HarmonyPrefix] private static bool Prefix(PhysGrabCart __instance) { int spawnedCartInstanceID = ShopCartSpawner.SpawnedCartInstanceID; if (spawnedCartInstanceID == 0 || ((Object)((Component)__instance).gameObject).GetInstanceID() != spawnedCartInstanceID) { return true; } CustomCartSteer(__instance); return false; } private static void CustomCartSteer(PhysGrabCart cart) { //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_028f: Unknown result type (might be due to invalid IL or missing references) //IL_0294: Unknown result type (might be due to invalid IL or missing references) //IL_02ad: Unknown result type (might be due to invalid IL or missing references) //IL_02b5: Unknown result type (might be due to invalid IL or missing references) //IL_02a6: Unknown result type (might be due to invalid IL or missing references) //IL_02ab: Unknown result type (might be due to invalid IL or missing references) //IL_02e8: Unknown result type (might be due to invalid IL or missing references) //IL_02ed: Unknown result type (might be due to invalid IL or missing references) //IL_02f2: Unknown result type (might be due to invalid IL or missing references) //IL_02f7: Unknown result type (might be due to invalid IL or missing references) //IL_0305: Unknown result type (might be due to invalid IL or missing references) //IL_030a: Unknown result type (might be due to invalid IL or missing references) //IL_030e: Unknown result type (might be due to invalid IL or missing references) //IL_0313: Unknown result type (might be due to invalid IL or missing references) //IL_0318: Unknown result type (might be due to invalid IL or missing references) //IL_0320: Unknown result type (might be due to invalid IL or missing references) //IL_0325: Unknown result type (might be due to invalid IL or missing references) //IL_032c: Unknown result type (might be due to invalid IL or missing references) //IL_0347: Unknown result type (might be due to invalid IL or missing references) //IL_034f: Unknown result type (might be due to invalid IL or missing references) //IL_0354: Unknown result type (might be due to invalid IL or missing references) //IL_0359: Unknown result type (might be due to invalid IL or missing references) //IL_035d: Unknown result type (might be due to invalid IL or missing references) //IL_0367: Unknown result type (might be due to invalid IL or missing references) //IL_036e: Unknown result type (might be due to invalid IL or missing references) //IL_0373: Unknown result type (might be due to invalid IL or missing references) //IL_0375: Unknown result type (might be due to invalid IL or missing references) //IL_037c: Unknown result type (might be due to invalid IL or missing references) //IL_0381: Unknown result type (might be due to invalid IL or missing references) //IL_0385: Unknown result type (might be due to invalid IL or missing references) //IL_0395: Unknown result type (might be due to invalid IL or missing references) //IL_039a: Unknown result type (might be due to invalid IL or missing references) //IL_03a4: Unknown result type (might be due to invalid IL or missing references) //IL_03b2: Unknown result type (might be due to invalid IL or missing references) //IL_03c0: Unknown result type (might be due to invalid IL or missing references) //IL_03ca: Unknown result type (might be due to invalid IL or missing references) //IL_03d8: Unknown result type (might be due to invalid IL or missing references) //IL_03e2: Unknown result type (might be due to invalid IL or missing references) //IL_03f8: Unknown result type (might be due to invalid IL or missing references) //IL_0403: Unknown result type (might be due to invalid IL or missing references) //IL_0408: Unknown result type (might be due to invalid IL or missing references) //IL_040d: Unknown result type (might be due to invalid IL or missing references) //IL_0412: Unknown result type (might be due to invalid IL or missing references) //IL_0417: Unknown result type (might be due to invalid IL or missing references) //IL_041b: Unknown result type (might be due to invalid IL or missing references) //IL_0430: Unknown result type (might be due to invalid IL or missing references) //IL_043c: Unknown result type (might be due to invalid IL or missing references) //IL_0441: Unknown result type (might be due to invalid IL or missing references) //IL_0445: Unknown result type (might be due to invalid IL or missing references) //IL_0454: Unknown result type (might be due to invalid IL or missing references) //IL_0459: Unknown result type (might be due to invalid IL or missing references) //IL_045b: Unknown result type (might be due to invalid IL or missing references) //IL_045d: Unknown result type (might be due to invalid IL or missing references) //IL_0462: Unknown result type (might be due to invalid IL or missing references) //IL_0467: Unknown result type (might be due to invalid IL or missing references) //IL_04bd: Unknown result type (might be due to invalid IL or missing references) //IL_04c2: Unknown result type (might be due to invalid IL or missing references) //IL_04c9: Unknown result type (might be due to invalid IL or missing references) //IL_04ce: Unknown result type (might be due to invalid IL or missing references) //IL_04d0: Unknown result type (might be due to invalid IL or missing references) //IL_04d4: Unknown result type (might be due to invalid IL or missing references) //IL_04d9: Unknown result type (might be due to invalid IL or missing references) //IL_04df: Unknown result type (might be due to invalid IL or missing references) //IL_04e4: Unknown result type (might be due to invalid IL or missing references) //IL_04e8: Unknown result type (might be due to invalid IL or missing references) //IL_04f6: Unknown result type (might be due to invalid IL or missing references) //IL_04fd: Unknown result type (might be due to invalid IL or missing references) float num = ShoppingCart.CartWalkDistance.Value; float num2 = ShoppingCart.CartSprintDistance.Value; float num3 = ShoppingCart.CartTurnMultiplier.Value; float num4 = ShoppingCart.CartTurnMinFactor.Value; float num5 = ShoppingCart.CartTurnMaxClamp.Value; if (float.IsNaN(num) || num < 0f) { num = 0f; } if (float.IsNaN(num2) || num2 < 0f) { num2 = 0f; } num = Mathf.Clamp(num, 0.7f, 4f); num2 = Mathf.Clamp(num2, 0.7f, 4f); if (num3 < 0f) { num3 = 0f; } if (num4 < 0f) { num4 = 0f; } if (num5 < 0f) { num5 = 0f; } PhysGrabObjectGrabArea component = ((Component)cart).GetComponent<PhysGrabObjectGrabArea>(); if ((Object)(object)component == (Object)null) { return; } List<PhysGrabber> listOfAllGrabbers = component.listOfAllGrabbers; foreach (PhysGrabber item in listOfAllGrabbers) { if (Object.op_Implicit((Object)(object)item)) { if (item.isLocal) { TutorialDirector.instance.playerUsedCart = true; } item.OverrideGrabPoint(cart.cartGrabPoint); } } if (!SemiFunc.IsMasterClientOrSingleplayer()) { return; } BoxCollider component2 = ((Component)cart.inCart).GetComponent<BoxCollider>(); float num10 = default(float); Vector3 val10 = default(Vector3); foreach (PhysGrabber item2 in listOfAllGrabbers) { if (!Object.op_Implicit((Object)(object)item2)) { continue; } Vector3 val = ((Component)item2.playerAvatar).transform.position + Vector3.up * 0.25f; if (item2.playerAvatar.isTumbling) { val = item2.playerAvatar.tumble.physGrabObject.centerPoint; } if (!(Vector3.Distance(((Collider)component2).ClosestPoint(val), val) >= 0.01f)) { continue; } Rigidbody component3 = ((Component)cart).GetComponent<Rigidbody>(); ((object)cart).GetType().GetMethod("CartMassOverride", BindingFlags.Instance | BindingFlags.NonPublic)?.Invoke(cart, new object[1] { 4f }); if ((Object)(object)item2 == (Object)(object)PhysGrabber.instance) { SemiFunc.PhysGrabberLocalChangeAlpha(0.1f); } if (!cart.cartActive && item2.initialPressTimer > 0f) { cart.cartActive = true; } if (!cart.cartActive || (Object)(object)item2 != (Object)(object)listOfAllGrabbers[0]) { break; } cart.cartBeingPulled = true; item2.OverridePhysGrabForcesDisable(0.1f); float num6 = num; float num7 = num2; if (cart.isSmallCart) { num6 = 1.75f; num7 = 2f; } Vector3 val2 = PlayerController.instance.rb.velocity; if (!item2.isLocal) { val2 = item2.playerAvatar.rbVelocityRaw; } bool flag = Vector3.Dot(val2, ((Component)cart).transform.forward) > 0f; float num8 = ((item2.playerAvatar.isSprinting && flag) ? num7 : num6); Vector3 val3 = ((Component)item2).transform.rotation * Vector3.back; Vector3 val4 = ((Component)item2.playerAvatar).transform.position - val3 * num8; float num9 = Mathf.Clamp(Vector3.Distance(((Component)cart).transform.position, val4 / 1f), 0f, 1f); Vector3 val5 = val4 - ((Component)cart).transform.position; Vector3 val6 = ((Vector3)(ref val5)).normalized * 5f * num9; val6 = Vector3.ClampMagnitude(val6, 5f); float y = component3.velocity.y; component3.velocity = Vector3.MoveTowards(component3.velocity, val6, num9 * 2f); component3.velocity = new Vector3(component3.velocity.x, y, component3.velocity.z); component3.velocity = Vector3.ClampMagnitude(component3.velocity, 5f); Quaternion val7 = Quaternion.LookRotation(((Component)item2).transform.position - ((Component)cart).transform.position, Vector3.up); Quaternion val8 = Quaternion.Euler(0f, ((Quaternion)(ref val7)).eulerAngles.y + 180f, 0f); val7 = component3.rotation; Quaternion val9 = Quaternion.Euler(0f, ((Quaternion)(ref val7)).eulerAngles.y, 0f); val7 = val8 * Quaternion.Inverse(val9); ((Quaternion)(ref val7)).ToAngleAxis(ref num10, ref val10); if (num10 > 180f) { num10 -= 360f; } float num11 = Mathf.Clamp(Mathf.Abs(num10) / 180f, num4, 1f) * num3; num11 = Mathf.Clamp(num11, 0f, num5); Vector3 val11 = MathF.PI / 180f * num10 * ((Vector3)(ref val10)).normalized * num11; val11 = Vector3.ClampMagnitude(val11, num5); component3.angularVelocity = Vector3.MoveTowards(component3.angularVelocity, val11, num11); component3.angularVelocity = Vector3.ClampMagnitude(component3.angularVelocity, num5); if (ShoppingCart.CartSteerDebugLogging.Value && Time.unscaledTime >= _nextCartSteerLogTime) { if (Mathf.Abs(_lastA - num6) > 0.001f || Mathf.Abs(_lastB - num7) > 0.001f || Mathf.Abs(_lastD - num8) > 0.001f || Mathf.Abs(_lastTurnMultiplier - num3) > 0.001f || Mathf.Abs(_lastTurnMinFactor - num4) > 0.001f || Mathf.Abs(_lastTurnMaxClamp - num5) > 0.001f) { ShoppingCart.LogInfo($"[CartSteer] dist walk={num6:F2} sprint={num7:F2} active={num8:F2} | turn mult={num3:F1} min={num4:F2} clamp={num5:F1}"); _lastA = num6; _lastB = num7; _lastD = num8; _lastTurnMultiplier = num3; _lastTurnMinFactor = num4; _lastTurnMaxClamp = num5; } _nextCartSteerLogTime = Time.unscaledTime + 1f; } } } } [HarmonyPatch(typeof(PhysGrabCart), "ObjectsInCart")] internal static class PhysGrabCartShopTotalPatch { private sealed class CartScanState { public readonly Dictionary<int, float> LastSeenTime = new Dictionary<int, float>(); public readonly Dictionary<int, int> LastValueDollars = new Dictionary<int, int>(); public readonly Dictionary<int, string> LastName = new Dictionary<int, string>(); public int LastTotalDollars; } private static readonly FieldRef<PhysGrabCart, Transform> InCartRef = AccessTools.FieldRefAccess<PhysGrabCart, Transform>("inCart"); private static readonly FieldRef<PhysGrabCart, int> HaulCurrentRef = AccessTools.FieldRefAccess<PhysGrabCart, int>("haulCurrent"); private static readonly FieldRef<PhysGrabCart, int> HaulPreviousRef = AccessTools.FieldRefAccess<PhysGrabCart, int>("haulPrevious"); private static readonly FieldRef<PhysGrabCart, float> HaulUpdateEffectTimerRef = AccessTools.FieldRefAccess<PhysGrabCart, float>("haulUpdateEffectTimer"); private static readonly FieldRef<PhysGrabCart, bool> ResetHaulTextRef = AccessTools.FieldRefAccess<PhysGrabCart, bool>("resetHaulText"); private static readonly FieldRef<PhysGrabCart, TextMeshPro> DisplayTextRef = AccessTools.FieldRefAccess<PhysGrabCart, TextMeshPro>("displayText"); private static readonly FieldRef<PhysGrabCart, Color> OriginalHaulColorRef = AccessTools.FieldRefAccess<PhysGrabCart, Color>("originalHaulColor"); private static readonly FieldRef<PhysGrabCart, float> ObjectInCartCheckTimerRef = AccessTools.FieldRefAccess<PhysGrabCart, float>("objectInCartCheckTimer"); private static readonly FieldRef<PhysGrabCart, List<PhysGrabObject>> ItemsInCartRef = AccessTools.FieldRefAccess<PhysGrabCart, List<PhysGrabObject>>("itemsInCart"); private static readonly FieldRef<PhysGrabCart, int> ItemsInCartCountRef = AccessTools.FieldRefAccess<PhysGrabCart, int>("itemsInCartCount"); private static float _nextDebugTime; private const float MISSING_GRACE_SECONDS = 1f; private static readonly Dictionary<int, CartScanState> StateByCart = new Dictionary<int, CartScanState>(); [HarmonyPrefix] private static bool Prefix(PhysGrabCart __instance) { //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_0697: Unknown result type (might be due to invalid IL or missing references) //IL_0689: Unknown result type (might be due to invalid IL or missing references) //IL_069c: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_06da: Unknown result type (might be due to invalid IL or missing references) //IL_06b0: Unknown result type (might be due to invalid IL or missing references) int spawnedCartPhysGrabObjectID = ShopCartSpawner.SpawnedCartPhysGrabObjectID; if (spawnedCartPhysGrabObjectID == 0) { return true; } PhysGrabObject component = ((Component)__instance).GetComponent<PhysGrabObject>(); if ((Object)(object)component == (Object)null || ((Object)component).GetInstanceID() != spawnedCartPhysGrabObjectID) { return true; } if (!StateByCart.TryGetValue(spawnedCartPhysGrabObjectID, out CartScanState value)) { value = new CartScanState(); StateByCart[spawnedCartPhysGrabObjectID] = value; } if (!SemiFunc.RunIsShop()) { return true; } if (SemiFunc.PlayerNearestDistance(((Component)__instance).transform.position) > 12f) { return false; } Transform val; try { val = InCartRef.Invoke(__instance); } catch { return true; } if ((Object)(object)val == (Object)null) { return true; } int num = 0; try { num = HaulCurrentRef.Invoke(__instance); } catch { } float num2; try { num2 = ObjectInCartCheckTimerRef.Invoke(__instance); } catch { num2 = 0f; } if (num2 > 0f) { try { ObjectInCartCheckTimerRef.Invoke(__instance) = Mathf.Max(0f, num2 - Time.deltaTime); } catch { } ApplyStableDisplay(__instance, value.LastTotalDollars); return false; } Vector3 val2 = val.position; Vector3 val3 = val.localScale / 2f; Quaternion rotation = val.rotation; BoxCollider component2 = ((Component)val).GetComponent<BoxCollider>(); if ((Object)(object)component2 != (Object)null) { val2 = ((Component)component2).transform.TransformPoint(component2.center); Vector3 lossyScale = ((Component)component2).transform.lossyScale; ((Vector3)(ref lossyScale))..ctor(Mathf.Abs(lossyScale.x), Mathf.Abs(lossyScale.y), Mathf.Abs(lossyScale.z)); val3 = Vector3.Scale(component2.size * 0.5f, lossyScale); rotation = ((Component)component2).transform.rotation; } Collider[] array = Physics.OverlapBox(val2, val3, rotation, -1, (QueryTriggerInteraction)2); HashSet<PhysGrabObject> hashSet = new HashSet<PhysGrabObject>(); HashSet<ItemAttributes> hashSet2 = new HashSet<ItemAttributes>(); List<PhysGrabObject> list = null; try { list = ItemsInCartRef.Invoke(__instance); list?.Clear(); } catch { } int num3 = 0; float unscaledTime = Time.unscaledTime; HashSet<int> hashSet3 = new HashSet<int>(); int num4 = 0; int num5 = 0; int num6 = 0; Collider[] array2 = array; foreach (Collider val4 in array2) { if ((Object)(object)val4 == (Object)null) { continue; } PhysGrabObject componentInParent = ((Component)val4).GetComponentInParent<PhysGrabObject>(); ItemAttributes val5 = null; ValuableObject val6 = null; if ((Object)(object)componentInParent != (Object)null) { val5 = ((Component)componentInParent).GetComponent<ItemAttributes>(); if ((Object)(object)val5 == (Object)null) { val5 = ((Component)componentInParent).GetComponentInChildren<ItemAttributes>(true); } val6 = ((Component)componentInParent).GetComponent<ValuableObject>(); if ((Object)(object)val6 == (Object)null) { val6 = ((Component)componentInParent).GetComponentInChildren<ValuableObject>(true); } } else { val5 = ((Component)val4).GetComponentInParent<ItemAttributes>(); val6 = ((Component)val4).GetComponentInParent<ValuableObject>(); } if ((Object)(object)componentInParent != (Object)null && (Object)(object)componentInParent == (Object)(object)component) { continue; } int instanceID; string name; if ((Object)(object)componentInParent != (Object)null) { if (!hashSet.Add(componentInParent)) { continue; } instanceID = ((Object)componentInParent).GetInstanceID(); name = ((Object)((Component)componentInParent).gameObject).name; list?.Add(componentInParent); num3++; } else { if (!((Object)(object)val5 != (Object)null) || hashSet2.Contains(val5)) { continue; } hashSet2.Add(val5); instanceID = ((Object)val5).GetInstanceID(); name = ((Object)((Component)val5).gameObject).name; } int? num7 = null; if ((Object)(object)val5 != (Object)null) { num7 = Mathf.Max(0, val5.value) * 1000; num4++; } else if ((Object)(object)val6 != (Object)null) { num7 = Mathf.RoundToInt(val6.dollarValueCurrent); num5++; } if (num7.HasValue) { value.LastSeenTime[instanceID] = unscaledTime; value.LastValueDollars[instanceID] = num7.Value; value.LastName[instanceID] = name; hashSet3.Add(instanceID); if (ShoppingCart.CartValueDebugLogging.Value && Time.unscaledTime >= _nextDebugTime && num6 < 12) { string text = LayerMask.LayerToName(((Component)val4).gameObject.layer); string text2 = (((Object)(object)componentInParent != (Object)null) ? ((Object)((Component)componentInParent).gameObject).name : "<null>"); string text3 = (((Object)(object)val5 != (Object)null) ? ((Object)((Component)val5).gameObject).name : "<null>"); int num8 = (((Object)(object)val5 != (Object)null) ? val5.value : 0); bool flag = (Object)(object)val6 != (Object)null; ShoppingCart.LogInfo($"[CartValueHit] col='{((Object)val4).name}' layer={((Component)val4).gameObject.layer}('{text}') trig={val4.isTrigger} pgo='{text2}' ia='{text3}' iaValue={num8} hasVal={flag}"); num6++; } } } int num9 = 0; if (value.LastSeenTime.Count > 0) { List<int> list2 = null; foreach (KeyValuePair<int, float> item in value.LastSeenTime) { int key = item.Key; float value2 = item.Value; if (!hashSet3.Contains(key) && unscaledTime - value2 > 1f) { if (list2 == null) { list2 = new List<int>(); } list2.Add(key); } } if (list2 != null) { foreach (int item2 in list2) { value.LastSeenTime.Remove(item2); value.LastValueDollars.Remove(item2); value.LastName.Remove(item2); } } foreach (KeyValuePair<int, int> lastValueDollar in value.LastValueDollars) { num9 += lastValueDollar.Value; } } value.LastTotalDollars = num9; try { ItemsInCartCountRef.Invoke(__instance) = num3; } catch { } try { ObjectInCartCheckTimerRef.Invoke(__instance) = 0.5f; } catch { } bool flag2 = num9 != num; try { HaulCurrentRef.Invoke(__instance) = num9; HaulPreviousRef.Invoke(__instance) = num9; HaulUpdateEffectTimerRef.Invoke(__instance) = 0f; ResetHaulTextRef.Invoke(__instance) = false; } catch { } if (flag2) { try { TextMeshPro val7 = DisplayTextRef.Invoke(__instance); Vector3 val8 = (((Object)(object)val7 != (Object)null) ? val7.transform.position : ((Component)__instance).transform.position); if (num9 > num) { Sound soundHaulIncrease = __instance.soundHaulIncrease; if (soundHaulIncrease != null) { soundHaulIncrease.Play(val8, 1f, 1f, 1f, 1f); } } else { Sound soundHaulDecrease = __instance.soundHaulDecrease; if (soundHaulDecrease != null) { soundHaulDecrease.Play(val8, 1f, 1f, 1f, 1f); } } } catch { } } ApplyStableDisplay(__instance, num9); if (ShoppingCart.CartValueDebugLogging.Value && Time.unscaledTime >= _nextDebugTime) { if (flag2) { ShoppingCart.LogInfo($"[CartValue] Updated haulCurrent from {num} to {num9}. itemsSeen={num4} valuablesSeen={num5} overlap={array.Length} retained={value.LastValueDollars.Count} grace={1f:F1}s"); } _nextDebugTime = Time.unscaledTime + 1f; } return false; } private static void ApplyStableDisplay(PhysGrabCart cart, int totalDollars) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) try { TextMeshPro val = DisplayTextRef.Invoke(cart); if ((Object)(object)val != (Object)null) { try { ((Graphic)val).color = OriginalHaulColorRef.Invoke(cart); } catch { } ((TMP_Text)val).text = "<color=#bd4300>$</color>" + SemiFunc.DollarGetString(Mathf.Max(0, totalDollars)); } } catch { } try { HaulUpdateEffectTimerRef.Invoke(cart) = 0f; ResetHaulTextRef.Invoke(cart) = true; } catch { } } } [HarmonyPatch(typeof(ShopManager), "ShopInitialize")] internal static class ShopCartSpawner { [HarmonyPatch(typeof(RunManager), "ChangeLevel")] private static class CleanupCartOnLevelChange { [HarmonyPostfix] private static void Postfix(bool _completedLevel, bool _levelFailed, ChangeLevelType _changeLevelType) { if (!SemiFunc.RunIsShop() && (Object)(object)spawnedCart != (Object)null) { if (SemiFunc.IsMultiplayer() && SemiFunc.IsMasterClientOrSingleplayer()) { PhotonNetwork.Destroy(spawnedCart); } else if (!SemiFunc.IsMultiplayer()) { Object.Destroy((Object)(object)spawnedCart); } spawnedCart = null; spawnedCartInstanceID = 0; spawnedCartPhotonViewID = 0; spawnedCartPhysGrabObjectID = 0; } } } [CompilerGenerated] private sealed class <FixCartPositionAfterSpawn>d__25 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public GameObject cart; public Vector3 targetPos; public Quaternion targetRot; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <FixCartPositionAfterSpawn>d__25(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_035e: Unknown result type (might be due to invalid IL or missing references) //IL_0360: Unknown result type (might be due to invalid IL or missing references) //IL_031f: Unknown result type (might be due to invalid IL or missing references) //IL_032b: Unknown result type (might be due to invalid IL or missing references) //IL_0337: Unknown result type (might be due to invalid IL or missing references) //IL_0340: Unknown result type (might be due to invalid IL or missing references) //IL_022f: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Unknown result type (might be due to invalid IL or missing references) //IL_02d0: Unknown result type (might be due to invalid IL or missing references) //IL_02d3: Unknown result type (might be due to invalid IL or missing references) //IL_02e2: Unknown result type (might be due to invalid IL or missing references) //IL_0281: Unknown result type (might be due to invalid IL or missing references) //IL_028b: Unknown result type (might be due to invalid IL or missing references) //IL_02a1: Unknown result type (might be due to invalid IL or missing references) //IL_0269: Unknown result type (might be due to invalid IL or missing references) //IL_0275: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = null; <>1__state = 1; return true; case 1: { <>1__state = -1; if ((Object)(object)cart == (Object)null) { return false; } Vector3 val = targetPos; ShoppingCart.LogInfo($"Applying 1-frame position fix. Target: {val}, Current: {cart.transform.position}"); Collider[] componentsInChildren = cart.GetComponentsInChildren<Collider>(); float num = float.MaxValue; Collider[] array = componentsInChildren; foreach (Collider val2 in array) { if (!val2.isTrigger) { Bounds bounds = val2.bounds; float y = ((Bounds)(ref bounds)).min.y; if (y < num) { num = y; } } } if (num != float.MaxValue) { float num2 = val.y; RaycastHit[] array2 = Physics.RaycastAll(new Vector3(val.x, val.y + 2f, val.z), Vector3.down, 20f, -1, (QueryTriggerInteraction)1); if (array2 != null && array2.Length != 0) { float num3 = float.NegativeInfinity; string arg = string.Empty; RaycastHit[] array3 = array2; for (int i = 0; i < array3.Length; i++) { RaycastHit val3 = array3[i]; Collider collider = ((RaycastHit)(ref val3)).collider; if (!((Object)(object)collider == (Object)null) && !collider.isTrigger && (((Object)collider).name == null || !((Object)collider).name.ToLowerInvariant().Contains("ceiling")) && ((RaycastHit)(ref val3)).point.y > num3) { num3 = ((RaycastHit)(ref val3)).point.y; arg = ((Object)collider).name ?? string.Empty; } } if (!float.IsNegativeInfinity(num3)) { num2 = num3; ShoppingCart.LogInfo($"Ground raycast chose Y={num2:F3} on '{arg}'"); } else { ShoppingCart.LogInfo("Ground raycast found only ignored hits; using target Y as ground level"); } } else { ShoppingCart.LogInfo("Ground raycast had no hits; using target Y as ground level"); } float num4 = num; float num5 = num2 + 0.02f - num4; ShoppingCart.LogInfo($"Bounds-based positioning: minY={num4:F3}, groundY={num2:F3}, deltaY={num5:F3}"); Vector3 position = cart.transform.position; position.y += num5; Rigidbody component = cart.GetComponent<Rigidbody>(); if ((Object)(object)component != (Object)null) { bool isKinematic = component.isKinematic; if (!isKinematic) { component.velocity = Vector3.zero; component.angularVelocity = Vector3.zero; } component.position = position; component.rotation = targetRot; component.WakeUp(); ShoppingCart.LogInfo($"Fixed cart position via Rigidbody to {position} (lifted {num5:F3}m, kinematic={isKinematic})"); } else { cart.transform.SetPositionAndRotation(position, targetRot); ShoppingCart.LogInfo($"Fixed cart position via Transform to {position} (lifted {num5:F3}m)"); } } else { ShoppingCart.LogWarning("No non-trigger colliders found on cart, using simple position fix"); Rigidbody component2 = cart.GetComponent<Rigidbody>(); if ((Object)(object)component2 != (Object)null) { component2.velocity = Vector3.zero; component2.angularVelocity = Vector3.zero; component2.position = val; component2.rotation = targetRot; component2.WakeUp(); } else { cart.transform.SetPositionAndRotation(val, targetRot); } } return false; } } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <LoadRegisterAndMaybeSpawnCart>d__16 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; private float <timeout>5__2; private AssetBundle <bundle>5__3; private AssetBundleRequest <allAssetsRequest>5__4; private AssetBundleCreateRequest <request>5__5; private Stream <s>5__6; private float <waitBudget>5__7; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <LoadRegisterAndMaybeSpawnCart>d__16(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 3) { try { } finally { <>m__Finally1(); } } <bundle>5__3 = null; <allAssetsRequest>5__4 = null; <request>5__5 = null; <s>5__6 = null; <>1__state = -2; } private bool MoveNext() { //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected O, but got Unknown //IL_03a5: Unknown result type (might be due to invalid IL or missing references) //IL_03af: Expected O, but got Unknown bool result; try { switch (<>1__state) { default: result = false; goto end_IL_0000; case 0: <>1__state = -1; if (!((Object)(object)spawnedCart != (Object)null)) { <timeout>5__2 = 10f; goto IL_008b; } result = false; goto end_IL_0000; case 1: <>1__state = -1; goto IL_008b; case 2: <>1__state = -1; <bundle>5__3 = <request>5__5.assetBundle; <request>5__5 = null; goto IL_02af; case 3: <>1__state = -3; <bundle>5__3 = <request>5__5.assetBundle; <request>5__5 = null; <>m__Finally1(); <s>5__6 = null; goto IL_02af; case 4: <>1__state = -1; cartPrefab = SelectCartPrefabDeterministically(<bundle>5__3, <allAssetsRequest>5__4.allAssets); if (!((Object)(object)cartPrefab == (Object)null)) { <bundle>5__3 = null; <allAssetsRequest>5__4 = null; goto IL_0347; } ShoppingCart.LogError("Cart prefab not found in asset bundle!"); result = false; goto end_IL_0000; case 5: { <>1__state = -1; goto IL_03c1; } IL_03c1: if (!(<waitBudget>5__7 > 0f) || AreAllPlayersPrefabReady()) { if (!AreAllPlayersPrefabReady()) { ShoppingCart.LogWarning("Not all players reported ShoppingCart prefab ready before spawn; spawning anyway."); } break; } <waitBudget>5__7 -= 0.25f; <>2__current = (object)new WaitForSeconds(0.25f); <>1__state = 5; result = true; goto end_IL_0000; IL_02af: if ((Object)(object)<bundle>5__3 == (Object)null) { ShoppingCart.LogError("Failed to load cart asset bundle!"); result = false; } else { <allAssetsRequest>5__4 = <bundle>5__3.LoadAllAssetsAsync(); <>2__current = <allAssetsRequest>5__4; <>1__state = 4; result = true; } goto end_IL_0000; IL_008b: if (<timeout>5__2 > 0f && ((Object)(object)LevelGenerator.Instance == (Object)null || !LevelGenerator.Instance.Generated)) { <timeout>5__2 -= 0.1f; <>2__current = (object)new WaitForSeconds(0.1f); <>1__state = 1; result = true; } else { if (!((Object)(object)cartPrefab == (Object)null)) { goto IL_0347; } string text = Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)ShoppingCart.Instance).Info.Location) ?? string.Empty, "shoppingcart"); <bundle>5__3 = null; if (File.Exists(text)) { <request>5__5 = AssetBundle.LoadFromFileAsync(text); <>2__current = <request>5__5; <>1__state = 2; result = true; } else { Assembly assembly = typeof(ShopCartSpawner).GetTypeInfo().Assembly; string text2 = null; string[] manifestResourceNames = assembly.GetManifestResourceNames(); foreach (string text3 in manifestResourceNames) { if (text3.EndsWith(".shoppingcart") || text3.EndsWith("shoppingcart")) { text2 = text3; break; } } if (text2 != null) { <s>5__6 = assembly.GetManifestResourceStream(text2); <>1__state = -3; if (<s>5__6 == null) { ShoppingCart.LogError("Embedded resource '" + text2 + "' could not be opened"); result = false; <>m__Finally1(); } else { byte[] array = new byte[<s>5__6.Length]; int num = <s>5__6.Read(array, 0, array.Length); if (num != array.Length) { ShoppingCart.LogWarning($"Read {num} bytes from embedded '{text2}' but expected {array.Length}"); } <request>5__5 = AssetBundle.LoadFromMemoryAsync(array); <>2__current = <request>5__5; <>1__state = 3; result = true; } } else { ShoppingCart.LogError("Cart asset bundle not found at: " + text + " and no embedded resource available"); result = false; } } } goto end_IL_0000; IL_0347: RegisterPrefabForPhoton(cartPrefab); if (SemiFunc.IsMultiplayer() && PhotonNetwork.InRoom) { MarkLocalPrefabReady(); } if (SemiFunc.IsMasterClientOrSingleplayer()) { if (!SemiFunc.IsMultiplayer() || !PhotonNetwork.InRoom) { break; } <waitBudget>5__7 = 8f; goto IL_03c1; } result = false; goto end_IL_0000; } SpawnCart(); result = false; end_IL_0000:; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } return result; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<s>5__6 != null) { ((IDisposable)<s>5__6).Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private static GameObject? cartPrefab; private static GameObject? spawnedCart; private static int spawnedCartInstanceID; private static int spawnedCartPhotonViewID; private static int spawnedCartPhysGrabObjectID; private const string PrefabReadyRoomPropKey = "Tolga.ShoppingCart.PrefabReady"; private const string PhotonPrefabKey = "Shopping Cart"; internal static GameObject? LatestSpawnedCart => spawnedCart; internal static int SpawnedCartInstanceID => spawnedCartInstanceID; internal static int SpawnedCartPhotonViewID => spawnedCartPhotonViewID; internal static int SpawnedCartPhysGrabObjectID => spawnedCartPhysGrabObjectID; [HarmonyPostfix] private static void Postfix() { if (SemiFunc.RunIsShop()) { ((MonoBehaviour)ShoppingCart.Instance).StartCoroutine(LoadRegisterAndMaybeSpawnCart()); } } [IteratorStateMachine(typeof(<LoadRegisterAndMaybeSpawnCart>d__16))] private static IEnumerator LoadRegisterAndMaybeSpawnCart() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <LoadRegisterAndMaybeSpawnCart>d__16(0); } private static GameObject? SelectCartPrefabDeterministically(AssetBundle bundle, Object[] allAssets) { string[] array = new string[4] { "Shopping Cart", "shopping_cart", "ShoppingCart", "Cart" }; foreach (string text in array) { try { GameObject val = bundle.LoadAsset<GameObject>(text); if ((Object)(object)val != (Object)null) { ShoppingCart.LogInfo("Selected cart prefab by name '" + text + "'"); return val; } } catch { } } GameObject[] array2 = (from g in allAssets.OfType<GameObject>() orderby ((Object)g).name select g).ToArray(); if (array2.Length == 0) { return null; } GameObject val2 = null; int num = int.MinValue; GameObject[] array3 = array2; foreach (GameObject val3 in array3) { int num2 = 0; string text2 = ((Object)val3).name.ToLowerInvariant(); if (text2.Contains("cart")) { num2 += 10; } if (text2.Contains("shopping")) { num2 += 5; } if ((Object)(object)val3.transform.Find("In Cart") != (Object)null) { num2 += 25; } if ((Object)(object)val3.transform.Find("Screen") != (Object)null) { num2 += 10; } if ((Object)(object)val3.transform.Find("Screen/Text") != (Object)null) { num2 += 10; } if ((Object)(object)val3.GetComponentInChildren<PhysGrabObject>(true) != (Object)null) { num2 += 10; } if ((Object)(object)val3.GetComponentInChildren<ShopCartComponent>(true) != (Object)null) { num2 += 10; } if ((Object)(object)val3.GetComponentInChildren<PhotonView>(true) != (Object)null) { num2 += 5; } if ((Object)(object)val2 == (Object)null || num2 > num) { val2 = val3; num = num2; } } string text3 = string.Join(", ", array2.Select((GameObject c) => ((Object)c).name)); ShoppingCart.LogInfo("Cart bundle prefab candidates (sorted): " + text3); ShoppingCart.LogInfo(string.Format("Selected cart prefab by heuristic: '{0}' (score={1})", ((val2 != null) ? ((Object)val2).name : null) ?? "<null>", num)); return val2; } private static void RegisterPrefabForPhoton(GameObject prefab) { if (!SemiFunc.IsMultiplayer()) { return; } IPunPrefabPool prefabPool = PhotonNetwork.PrefabPool; DefaultPool val = (DefaultPool)(object)((prefabPool is DefaultPool) ? prefabPool : null); if (val != null) { val.ResourceCache["Shopping Cart"] = prefab; if (!string.IsNullOrEmpty(((Object)prefab).name)) { val.ResourceCache[((Object)prefab).name] = prefab; } } else { ShoppingCart.LogWarning("PhotonNetwork.PrefabPool is '" + (((object)PhotonNetwork.PrefabPool)?.GetType().FullName ?? "<null>") + "', expected DefaultPool; cart may fail to spawn on some clients."); } } private static void MarkLocalPrefabReady() { //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_0016: Expected O, but got Unknown //IL_0017: Expected O, but got Unknown try { Hashtable val = new Hashtable(); ((Dictionary<object, object>)val).Add((object)"Tolga.ShoppingCart.PrefabReady", (object)true); Hashtable val2 = val; PhotonNetwork.LocalPlayer.SetCustomProperties(val2, (Hashtable)null, (WebFlags)null); } catch { } } private static bool AreAllPlayersPrefabReady() { Player[] playerList = PhotonNetwork.PlayerList; foreach (Player val in playerList) { if (val.CustomProperties == null) { return false; } if (!((Dictionary<object, object>)(object)val.CustomProperties).TryGetValue((object)"Tolga.ShoppingCart.PrefabReady", out object value)) { return false; } if (!(value is bool) || !(bool)value) { return false; } } return true; } private static Camera? GetBestCamera() { if ((Object)(object)Camera.main != (Object)null && ((Behaviour)Camera.main).isActiveAndEnabled) { return Camera.main; } Camera[] array = Object.FindObjectsOfType<Camera>(); foreach (Camera val in array) { if (((Behaviour)val).isActiveAndEnabled && ((Component)val).CompareTag("MainCamera")) { return val; } } array = Object.FindObjectsOfType<Camera>(); foreach (Camera val2 in array) { if (((Behaviour)val2).isActiveAndEnabled) { return val2; } } ShoppingCart.LogWarning("No active camera found for cart spawn"); return null; } private static bool TryGetCameraSpawn(out Vector3 spawnPos, out Quaternion spawnRot) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_002d: 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) //IL_0039: 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_004c: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) spawnPos = Vector3.zero; spawnRot = Quaternion.identity; Camera bestCamera = GetBestCamera(); if ((Object)(object)bestCamera == (Object)null) { return false; } Vector3 position = ((Component)bestCamera).transform.position; Vector3 forward = ((Component)bestCamera).transform.forward; float num = 2f; float num2 = 3f; RaycastHit val = default(RaycastHit); if (Physics.Raycast(position, forward, ref val, num2, -1, (QueryTriggerInteraction)1)) { num = Mathf.Clamp(((RaycastHit)(ref val)).distance - 0.4f, 0.8f, 2f); ShoppingCart.LogInfo($"F8: Raycast hit '{((Object)((RaycastHit)(ref val)).collider).name}' at {((RaycastHit)(ref val)).distance:F2}m, placing at {num:F2}m"); } spawnPos = position + forward * num; spawnRot = Quaternion.Euler(0f, ((Component)bestCamera).transform.eulerAngles.y, 0f); ShoppingCart.LogInfo($"Spawned cart in air at: {spawnPos} (2m away, let it fall naturally)"); return true; } private static void SpawnCart() { //IL_002a: 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_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_02fc: Unknown result type (might be due to invalid IL or missing references) //IL_02fd: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)cartPrefab == (Object)null) { return; } string text = "Shopping Cart"; Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(0.49f, 0.97f, -1.28f); Quaternion identity = Quaternion.identity; ShoppingCart.LogInfo($"Spawning cart at fixed position {val} (rotation {((Quaternion)(ref identity)).eulerAngles})"); ShoppingCart.LogInfo($"Cart will spawn and then run bounds-based settle from {val}"); if (SemiFunc.IsMultiplayer()) { RegisterPrefabForPhoton(cartPrefab); spawnedCart = PhotonNetwork.InstantiateRoomObject(text, val, identity, (byte)0, (object[])null); } else { spawnedCart = Object.Instantiate<GameObject>(cartPrefab, val, identity); } if ((Object)(object)LevelGenerator.Instance != (Object)null && (Object)(object)LevelGenerator.Instance.ItemParent != (Object)null) { spawnedCart.transform.parent = LevelGenerator.Instance.ItemParent.transform; } if ((Object)(object)spawnedCart != (Object)null) { spawnedCartInstanceID = ((Object)spawnedCart).GetInstanceID(); PhotonView component = spawnedCart.GetComponent<PhotonView>(); spawnedCartPhotonViewID = (((Object)(object)component != (Object)null) ? component.ViewID : 0); PhysGrabObject componentInChildren = spawnedCart.GetComponentInChildren<PhysGrabObject>(true); spawnedCartPhysGrabObjectID = (((Object)(object)componentInChildren != (Object)null) ? ((Object)componentInChildren).GetInstanceID() : 0); DisableVanillaCostUI(spawnedCart); try { ShopCartComponent componentInChildren2 = spawnedCart.GetComponentInChildren<ShopCartComponent>(true); int num = 0; MonoBehaviour[] componentsInChildren = spawnedCart.GetComponentsInChildren<MonoBehaviour>(true); for (int i = 0; i < componentsInChildren.Length; i++) { if ((Object)(object)componentsInChildren[i] == (Object)null) { num++; } } string text2 = "<no ShopCartComponent>"; string text3 = "<no ShopCartComponent>"; if ((Object)(object)componentInChildren2 != (Object)null) { Transform val2 = ((Component)componentInChildren2).transform.Find("In Cart"); Collider val3 = (((Object)(object)val2 != (Object)null) ? ((Component)val2).GetComponent<Collider>() : null); text2 = (((Object)(object)val3 != (Object)null) ? $"In Cart collider={((object)val3).GetType().Name} isTrigger={val3.isTrigger}" : "In Cart collider=<null>"); Transform val4 = ((Component)componentInChildren2).transform.Find("Screen/Text"); TextMeshPro val5 = (((Object)(object)val4 != (Object)null) ? ((Component)val4).GetComponent<TextMeshPro>() : null); text3 = (((Object)(object)val5 != (Object)null) ? ("Screen TMP='" + ((Object)val5).name + "'") : "Screen TMP=<null>"); } ShoppingCart.LogInfo($"Spawn sanity: ShopCartComponent={(Object)(object)componentInChildren2 != (Object)null}, {text2}, {text3}, missingMonoBehaviours={num}"); ShoppingCart.LogInfo($"Spawn sanity IDs: cartInst={spawnedCartInstanceID}, cartPv={spawnedCartPhotonViewID}, cartPhysGrabObjectInst={spawnedCartPhysGrabObjectID}"); } catch (Exception ex) { ShoppingCart.LogWarning("Spawn sanity failed: " + ex.GetType().Name + ": " + ex.Message); } InitializeCart(spawnedCart); ((MonoBehaviour)ShoppingCart.Instance).StartCoroutine(FixCartPositionAfterSpawn(spawnedCart, val, identity)); ShoppingCart.LogInfo($"Cart instantiated (InstanceID: {spawnedCartInstanceID}). Will position via gravity + bounds-fix."); } else { ShoppingCart.LogError("Failed to spawn cart!"); } } [IteratorStateMachine(typeof(<FixCartPositionAfterSpawn>d__25))] private static IEnumerator FixCartPositionAfterSpawn(GameObject cart, Vector3 targetPos, Quaternion targetRot) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: 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) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <FixCartPositionAfterSpawn>d__25(0) { cart = cart, targetPos = targetPos, targetRot = targetRot }; } private static void InitializeCart(GameObject cart) { } private static void DisableVanillaCostUI(GameObject cart) { int num = 0; MonoBehaviour[] componentsInChildren = cart.GetComponentsInChildren<MonoBehaviour>(true); foreach (MonoBehaviour val in componentsInChildren) { if (!((Object)(object)val == (Object)null)) { switch (((object)val).GetType().Name) { case "WorldSpaceUIValue": case "ShopCostUI": case "CurrencyUI": ((Behaviour)val).enabled = false; num++; break; } } } if (num > 0) { ShoppingCart.LogInfo($"Disabled {num} vanilla cost UI component(s) on spawned cart"); } } } [BepInPlugin("Tolga.ShoppingCart", "ShoppingCart", "1.0")] public class ShoppingCart : BaseUnityPlugin { private bool _f8WasDown; private float _nextMoveTime; internal static ShoppingCart Instance { get; private set; } internal static ManualLogSource Logger => Instance._logger; private ManualLogSource _logger => ((BaseUnityPlugin)this).Logger; internal Harmony? Harmony { get; set; } internal static ConfigEntry<float> CartWalkDistance { get; private set; } internal static ConfigEntry<float> CartSprintDistance { get; private set; } internal static ConfigEntry<float> CartTurnMultiplier { get; private set; } internal static ConfigEntry<float> CartTurnMinFactor { get; private set; } internal static ConfigEntry<float> CartTurnMaxClamp { get; private set; } internal static ConfigEntry<bool> CartDebugLogging { get; private set; } internal static ConfigEntry<bool> CartPriceDebugLogging { get; private set; } internal static ConfigEntry<bool> CartValueDebugLogging { get; private set; } internal static ConfigEntry<bool> CartCostPopupDebugLogging { get; private set; } internal static ConfigEntry<bool> CartSteerDebugLogging { get; private set; } internal static ConfigEntry<bool> CartInfoLogging { get; private set; } internal static ConfigEntry<bool> CartWarningLogging { get; private set; } internal static ConfigEntry<bool> CartErrorLogging { get; private set; } internal static bool AnyInfoLoggingEnabled { get { if (!IsEnabled(CartInfoLogging) && !IsEnabled(CartDebugLogging) && !IsEnabled(CartPriceDebugLogging) && !IsEnabled(CartValueDebugLogging) && !IsEnabled(CartCostPopupDebugLogging)) { return IsEnabled(CartSteerDebugLogging); } return true; } } internal static bool AnyWarningLoggingEnabled { get { if (!IsEnabled(CartWarningLogging)) { return IsEnabled(CartDebugLogging); } return true; } } internal static bool AnyErrorLoggingEnabled { get { if (!IsEnabled(CartErrorLogging)) { return IsEnabled(CartDebugLogging); } return true; } } private void Awake() { Instance = this; ((Component)this).gameObject.transform.parent = null; ((Object)((Component)this).gameObject).hideFlags = (HideFlags)61; BindConfig(); LogInfo($"Config: InfoLogging={CartInfoLogging.Value}, WarningLogging={CartWarningLogging.Value}, ErrorLogging={CartErrorLogging.Value}, DebugLogging={CartDebugLogging.Value}, PriceDebugLogging={CartPriceDebugLogging.Value}, ValueDebugLogging={CartValueDebugLogging.Value}, CostPopupDebugLogging={CartCostPopupDebugLogging.Value}, SteerDebugLogging={CartSteerDebugLogging.Value}"); Patch(); LogInfo($"{((BaseUnityPlugin)this).Info.Metadata.GUID} v{((BaseUnityPlugin)this).Info.Metadata.Version} has loaded!"); } private void BindConfig() { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Expected O, but got Unknown //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Expected O, but got Unknown AcceptableValueRange<float> val = new AcceptableValueRange<float>(0.7f, 4f); ConfigurationManagerAttributes configurationManagerAttributes = new ConfigurationManagerAttributes { Increment = 0.01f }; CartWalkDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Cart", "WalkDistance", 1.1f, new ConfigDescription("How far the cart stays from you while walking.", (AcceptableValueBase)(object)val, new object[1] { configurationManagerAttributes })); CartSprintDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Cart", "SprintDistance", 1.75f, new ConfigDescription("How far the cart stays from you while sprinting (and moving forward with the cart).", (AcceptableValueBase)(object)val, new object[1] { configurationManagerAttributes })); CartTurnMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Cart", "TurnMultiplier", 20f, "Turn speed multiplier used when steering the cart."); CartTurnMinFactor = ((BaseUnityPlugin)this).Config.Bind<float>("Cart", "TurnMinFactor", 0.2f, "Minimum turning factor clamp (vanilla is 0.2). Higher = more responsive at small angles."); CartTurnMaxClamp = ((BaseUnityPlugin)this).Config.Bind<float>("Cart", "TurnMaxClamp", 4f, "Maximum turn clamp used for angular velocity (vanilla is 4). Higher = faster snap turns."); CartDebugLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Cart", "DebugLogging", false, "Enable verbose debug logging for cart patches."); CartPriceDebugLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Cart", "PriceDebugLogging", false, "Enable verbose debug logging for cart price display."); CartValueDebugLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Cart", "ValueDebugLogging", false, "Enable debug logging for cart item scanning and total calculation."); CartCostPopupDebugLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Cart", "CostPopupDebugLogging", false, "Enable debug logging for WorldSpaceUIValue (the '-$...K' popup) suppression."); CartSteerDebugLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Cart", "SteerDebugLogging", false, "Enable debug logging for CartSteer distance/turn calculations."); CartInfoLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Cart", "InfoLogging", false, "Enable informational logs from the mod."); CartWarningLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Cart", "WarningLogging", false, "Enable warning logs from the mod."); CartErrorLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Cart", "ErrorLogging", false, "Enable error logs from the mod."); } private static bool IsEnabled(ConfigEntry<bool>? entry) { return entry?.Value ?? false; } internal static void LogInfo(string message) { if (AnyInfoLoggingEnabled) { Logger.LogInfo((object)message); } } internal static void LogWarning(string message) { if (AnyWarningLoggingEnabled) { Logger.LogWarning((object)message); } } internal static void LogError(string message) { if (AnyErrorLoggingEnabled) { Logger.LogError((object)message); } } internal void Patch() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown //IL_0025: Expected O, but got Unknown if (Harmony == null) { Harmony val = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID); Harmony val2 = val; Harmony = val; } Harmony.PatchAll(); } internal void Unpatch() { Harmony? harmony = Harmony; if (harmony != null) { harmony.UnpatchSelf(); } } private void Update() { if (SemiFunc.RunIsShop()) { bool key = Input.GetKey((KeyCode)289); if (key && !_f8WasDown && Time.time >= _nextMoveTime) { _nextMoveTime = Time.time + 0.25f; LogInfo("F8 key pressed - triggering MoveCartToLook()"); MoveCartToLook(); } _f8WasDown = key; } } private Camera? GetBestCamera() { if (Object.op_Implicit((Object)(object)Camera.main) && ((Behaviour)Camera.main).isActiveAndEnabled) { return Camera.main; } Camera val = ((IEnumerable<Camera>)Object.FindObjectsOfType<Camera>()).FirstOrDefault((Func<Camera, bool>)((Camera c) => ((Behaviour)c).isActiveAndEnabled && ((Component)c).CompareTag("MainCamera"))); if ((Object)(object)val != (Object)null) { return val; } Camera? obj = ((IEnumerable<Camera>)Object.FindObjectsOfType<Camera>()).FirstOrDefault((Func<Camera, bool>)((Camera c) => ((Behaviour)c).isActiveAndEnabled)); if ((Object)(object)obj == (Object)null) { LogWarning("No active camera found!"); } return obj; } private void MoveCartToLook() { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: 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_007c: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) Camera bestCamera = GetBestCamera(); if ((Object)(object)bestCamera == (Object)null) { LogWarning("F8: No active camera found"); return; } GameObject val = ShopCartSpawner.LatestSpawnedCart; if ((Object)(object)val == (Object)null) { val = GameObject.Find("Shopping Cart(Clone)") ?? GameObject.Find("shopping_cart(Clone)"); } if ((Object)(object)val == (Object)null) { LogWarning("F8 pressed but shopping_cart(Clone) not found. Cart may not have spawned yet."); return; } Vector3 position = ((Component)bestCamera).transform.position; Vector3 forward = ((Component)bestCamera).transform.forward; float num = 2f; float num2 = 3f; RaycastHit val2 = default(RaycastHit); if (Physics.Raycast(position, forward, ref val2, num2, -1, (QueryTriggerInteraction)1)) { num = Mathf.Clamp(((RaycastHit)(ref val2)).distance - 0.4f, 0.8f, 2f); LogInfo($"F8: Raycast hit '{((Object)((RaycastHit)(ref val2)).collider).name}' at {((RaycastHit)(ref val2)).distance:F2}m, placing at {num:F2}m"); } Vector3 val3 = position + forward * num; val.transform.SetPositionAndRotation(val3, Quaternion.Euler(0f, ((Component)bestCamera).transform.eulerAngles.y, 0f)); Rigidbody component = val.GetComponent<Rigidbody>(); if ((Object)(object)component != (Object)null) { component.velocity = Vector3.zero; component.angularVelocity = Vector3.zero; component.WakeUp(); } LogInfo($"Spawned cart in air at: {val3} (2m away, let it fall naturally)"); } } internal sealed class ConfigurationManagerAttributes { public float? Increment { get; set; } } [HarmonyPatch(typeof(WorldSpaceUIValue), "Show")] internal static class WorldSpaceUIValuePatch { private static float _nextCostPopupDebugTime; [HarmonyPrefix] private static bool Prefix(WorldSpaceUIValue __instance, PhysGrabObject _grabObject, int _value, bool _cost, Vector3 _offset) { if (!_cost) { return true; } int spawnedCartPhotonViewID = ShopCartSpawner.SpawnedCartPhotonViewID; int spawnedCartInstanceID = ShopCartSpawner.SpawnedCartInstanceID; int spawnedCartPhysGrabObjectID = ShopCartSpawner.SpawnedCartPhysGrabObjectID; if (spawnedCartPhotonViewID == 0 && spawnedCartInstanceID == 0 && spawnedCartPhysGrabObjectID == 0) { return true; } if ((Object)(object)_grabObject == (Object)null) { return true; } PhotonView component = ((Component)_grabObject).GetComponent<PhotonView>(); bool flag = false; if (spawnedCartPhysGrabObjectID != 0 && ((Object)_grabObject).GetInstanceID() == spawnedCartPhysGrabObjectID) { flag = true; } else if ((Object)(object)component != (Object)null && spawnedCartPhotonViewID != 0 && component.ViewID == spawnedCartPhotonViewID) { flag = true; } else { ShopCartComponent componentInParent = ((Component)_grabObject).GetComponentInParent<ShopCartComponent>(); if ((Object)(object)componentInParent != (Object)null && spawnedCartInstanceID != 0 && ((Object)((Component)componentInParent).gameObject).GetInstanceID() == spawnedCartInstanceID) { flag = true; } } if (ShoppingCart.CartCostPopupDebugLogging.Value && Time.unscaledTime >= _nextCostPopupDebugTime) { int num = (((Object)(object)component != (Object)null) ? component.ViewID : 0); int instanceID = ((Object)_grabObject).GetInstanceID(); int instanceID2 = ((Object)((Component)_grabObject).gameObject).GetInstanceID(); ShopCartComponent componentInParent2 = ((Component)_grabObject).GetComponentInParent<ShopCartComponent>(); int num2 = (((Object)(object)componentInParent2 != (Object)null) ? ((Object)((Component)componentInParent2).gameObject).GetInstanceID() : 0); ShoppingCart.LogInfo(string.Format("[CostPopup] Show(value={0}, cost={1}) grab='{2}' pv={3} pgoInst={4} goInst={5} sccInst={6} | spawnedPv={7} spawnedCartInst={8} spawnedPgoInst={9} => {10}", _value, _cost, ((Object)((Component)_grabObject).gameObject).name, num, instanceID, instanceID2, num2, spawnedCartPhotonViewID, spawnedCartInstanceID, spawnedCartPhysGrabObjectID, flag ? "BLOCK" : "ALLOW")); _nextCostPopupDebugTime = Time.unscaledTime + 1f; } return !flag; } } }