using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.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;
}
}
}