Decompiled source of Echo v0.11.3

BepInEx/plugins/Robin-Echo/RepoEnemyMod.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Threading;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using Photon.Voice;
using Photon.Voice.PUN;
using Photon.Voice.Unity;
using REPOLib.Modules;
using REPOLib.Objects.Sdk;
using TMPro;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.Events;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
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: AssemblyCompany("RepoEnemyMod")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.11.3.0")]
[assembly: AssemblyInformationalVersion("0.11.3")]
[assembly: AssemblyProduct("RepoEnemyMod")]
[assembly: AssemblyTitle("RepoEnemyMod")]
[assembly: AssemblyVersion("0.11.3.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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]
	[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]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace RepoEnemyMod
{
	public sealed class CartMischiefCycle
	{
		public enum Stage
		{
			Idle,
			Approaching,
			Helping,
			Readying,
			Stealing
		}

		private float heldSeconds;

		public Stage Current { get; private set; }

		public float Remaining { get; private set; }

		public void Begin()
		{
			Current = Stage.Approaching;
			Remaining = 12f;
		}

		public void Hold()
		{
			Current = Stage.Helping;
			Remaining = 3f;
			heldSeconds = 0f;
		}

		public void Cancel()
		{
			Current = Stage.Idle;
			Remaining = 0f;
		}

		public void Steal()
		{
			Current = Stage.Stealing;
			Remaining = 12f;
		}

		public void Step(float dt, bool loaded, bool unwatched, bool interrupted)
		{
			dt = ((float.IsNaN(dt) || float.IsInfinity(dt)) ? 0f : Math.Max(0f, dt));
			if (interrupted)
			{
				Cancel();
				return;
			}
			Remaining -= Math.Max(0f, dt);
			if (Current == Stage.Helping || Current == Stage.Readying)
			{
				heldSeconds += Math.Max(0f, dt);
			}
			bool flag = unwatched || heldSeconds >= 8f;
			if (Current == Stage.Approaching && Remaining <= 0f)
			{
				Cancel();
			}
			else if (Current == Stage.Helping && Remaining <= 0f && loaded && flag)
			{
				Current = Stage.Readying;
				Remaining = 1.2f;
			}
			else if (Current == Stage.Readying)
			{
				if (!loaded || !flag)
				{
					Current = Stage.Helping;
					Remaining = 2f;
				}
				else if (Remaining <= 0f)
				{
					Steal();
				}
			}
			else if (Current == Stage.Stealing && (!loaded || Remaining <= 0f))
			{
				Cancel();
			}
		}
	}
	public static class CartTheftMotion
	{
		public const float Speed = 4.5f;

		public const float AccelerationLimit = 8f;

		public const float HeldDrag = 0.5f;

		public const float PullDistance = 2.6f;

		public const float PushDistance = 3.4f;

		public static bool CanRefreshOverride(float secondsRemaining, float currentValue, float heldValue)
		{
			if (Finite(secondsRemaining) && Finite(currentValue) && Finite(heldValue) && heldValue >= 0f)
			{
				if (!(secondsRemaining <= 0f))
				{
					return currentValue <= heldValue;
				}
				return true;
			}
			return false;
		}

		public static float LeaderPace(float separation)
		{
			if (!Finite(separation) || separation < 0f)
			{
				return 0f;
			}
			return 4.5f * Math.Max(0f, Math.Min(1f, (3.8f - separation) / 0.6f));
		}

		public static (float X, float Z) Acceleration(float errorX, float errorZ, float leaderX, float leaderZ, float velocityX, float velocityZ, float speedLimit)
		{
			if (!Finite(errorX) || !Finite(errorZ) || !Finite(leaderX) || !Finite(leaderZ) || !Finite(velocityX) || !Finite(velocityZ) || !Finite(speedLimit) || speedLimit < 0f)
			{
				return (X: 0f, Z: 0f);
			}
			double x = (double)errorX * 3.0 + (double)leaderX;
			double z = (double)errorZ * 3.0 + (double)leaderZ;
			Clamp(ref x, ref z, Math.Min(4.5f, speedLimit));
			x = (x - (double)velocityX) * 5.0 + x * 0.5;
			z = (z - (double)velocityZ) * 5.0 + z * 0.5;
			Clamp(ref x, ref z, 8f);
			return (X: (float)x, Z: (float)z);
		}

		private static void Clamp(ref double x, ref double z, float limit)
		{
			double num = Math.Sqrt(x * x + z * z);
			if (num > (double)limit)
			{
				x = x / num * (double)limit;
				z = z / num * (double)limit;
			}
		}

		private static bool Finite(float value)
		{
			if (!float.IsNaN(value))
			{
				return !float.IsInfinity(value);
			}
			return false;
		}
	}
	public sealed class CartTheftProgress
	{
		private float bestRemaining;

		private float idleSeconds;

		private float blockedSeconds;

		public void Begin(float remaining)
		{
			bestRemaining = remaining;
			idleSeconds = (blockedSeconds = 0f);
		}

		public bool ShouldRelease(float dt, float remaining, bool physicallyBlocked)
		{
			if (float.IsNaN(dt) || float.IsInfinity(dt) || dt < 0f || float.IsNaN(remaining) || float.IsInfinity(remaining) || remaining < 0f)
			{
				return true;
			}
			if (remaining < bestRemaining - 0.15f)
			{
				bestRemaining = remaining;
				idleSeconds = 0f;
			}
			else
			{
				idleSeconds += dt;
			}
			blockedSeconds = (physicallyBlocked ? (blockedSeconds + dt) : 0f);
			if (!(idleSeconds >= 2.5f))
			{
				return blockedSeconds >= 1.25f;
			}
			return true;
		}
	}
	public static class CartApproachPath
	{
		public static int[]? Find(float[,] edges)
		{
			int length = edges.GetLength(0);
			if (length < 2 || edges.GetLength(1) != length)
			{
				throw new ArgumentException("Expected a square route graph.", "edges");
			}
			float[] array = new float[length];
			int[] array2 = new int[length];
			bool[] array3 = new bool[length];
			for (int i = 0; i < length; i++)
			{
				array[i] = float.PositiveInfinity;
				array2[i] = -1;
			}
			array[0] = 0f;
			for (int j = 0; j < length; j++)
			{
				int num = -1;
				for (int k = 0; k < length; k++)
				{
					if (!array3[k] && (num < 0 || array[k] < array[num]))
					{
						num = k;
					}
				}
				if (num < 0 || float.IsPositiveInfinity(array[num]) || num == 1)
				{
					break;
				}
				array3[num] = true;
				for (int l = 1; l < length; l++)
				{
					float num2 = edges[num, l];
					if (!array3[l] && !float.IsNaN(num2) && !(num2 < 0f) && !float.IsInfinity(num2))
					{
						float num3 = array[num] + num2;
						if (num3 < array[l])
						{
							array[l] = num3;
							array2[l] = num;
						}
					}
				}
			}
			if (array2[1] < 0)
			{
				return null;
			}
			List<int> list = new List<int>();
			for (int num4 = 1; num4 != 0; num4 = array2[num4])
			{
				list.Add(num4);
			}
			list.Reverse();
			return list.ToArray();
		}
	}
	internal static class DisguiseSelection
	{
		internal readonly struct CosmeticOption : IEquatable<CosmeticOption>
		{
			internal readonly int Slot;

			internal readonly string Resource;

			internal CosmeticOption(int slot, string resource)
			{
				Slot = slot;
				Resource = resource;
			}

			public bool Equals(CosmeticOption other)
			{
				if (Slot == other.Slot)
				{
					return Resource == other.Resource;
				}
				return false;
			}

			public override bool Equals(object? other)
			{
				if (other is CosmeticOption other2)
				{
					return Equals(other2);
				}
				return false;
			}

			public override int GetHashCode()
			{
				return Slot;
			}
		}

		internal static bool HeadAccessorySlot(int slot)
		{
			if (slot != 0 && slot != 17 && slot != 18 && slot != 24 && slot != 25 && slot != 30 && slot != 31)
			{
				return slot == 32;
			}
			return true;
		}

		internal static int Choose(int[] players, int current, Func<int, int> randomIndex)
		{
			if (current >= 0 && Array.IndexOf(players, current) >= 0)
			{
				return current;
			}
			if (players.Length != 0)
			{
				return players[randomIndex(players.Length)];
			}
			return -1;
		}

		internal static int ChooseAfterRebirth(int[] players, int current, int previous, Func<int, int> randomIndex)
		{
			return Choose((current < 0 && players.Length > 1) ? players.Where((int id) => id != previous).ToArray() : players, current, randomIndex);
		}

		internal static CosmeticOption? ChooseCosmetic(CosmeticOption[] available, CosmeticOption[] equipped, int copiedPlayer, int enemyIdentity)
		{
			CosmeticOption[] array = (from c in available.Where((CosmeticOption c) => c.Slot >= 0 && !string.IsNullOrEmpty(c.Resource) && equipped.Count((CosmeticOption e) => e.Slot == c.Slot) <= 1 && !equipped.Contains(c)).Distinct()
				orderby c.Slot
				select c).ThenBy<CosmeticOption, string>((CosmeticOption c) => c.Resource, StringComparer.Ordinal).ToArray();
			if (array.Length == 0)
			{
				return null;
			}
			int[] array2 = array.Select((CosmeticOption c) => c.Slot).Distinct().ToArray();
			uint num = Mix((uint)copiedPlayer);
			int slot = array2[(uint)((ulong)((long)num + (long)(uint)enemyIdentity) % (ulong)(uint)array2.Length)];
			CosmeticOption[] array3 = array.Where((CosmeticOption c) => c.Slot == slot).ToArray();
			return array3[(uint)((ulong)((long)Mix(num ^ (uint)slot) + (long)((uint)enemyIdentity / (uint)array2.Length)) % (ulong)(uint)array3.Length)];
		}

		internal static string CosmeticResource(string objectName)
		{
			return "cosmetics/" + objectName.Replace("(Clone)", "").Trim();
		}

		internal static CosmeticOption? ChooseRemoval(CosmeticOption[] safeCandidates, CosmeticOption[] equipped, int copiedPlayer, int enemyIdentity)
		{
			return ChooseCosmetic(safeCandidates.Where((CosmeticOption c) => equipped.Contains(c) && equipped.Count((CosmeticOption e) => e.Slot == c.Slot) == 1).ToArray(), Array.Empty<CosmeticOption>(), copiedPlayer, enemyIdentity);
		}

		internal static bool ShowFlashlight(bool ready, bool level, bool fallen, bool diving, float health)
		{
			if (ready && level && !fallen && !diving && health > 0f)
			{
				return !float.IsInfinity(health);
			}
			return false;
		}

		internal static float FlashAmount(float until, float now)
		{
			if (!float.IsNaN(until) && !float.IsNaN(now) && !float.IsInfinity(until) && !float.IsInfinity(now))
			{
				return Math.Max(0f, Math.Min(1f, (until - now) / 0.4f));
			}
			return 0f;
		}

		private static uint Mix(uint value)
		{
			value ^= value >> 16;
			value *= 2146121005;
			value ^= value >> 15;
			value *= 2221713035u;
			return value ^ (value >> 16);
		}
	}
	internal static class EchoAdditionalAttacks
	{
		private sealed class Focus
		{
			internal Vector3 Point;

			internal float Until;
		}

		[HarmonyPatch(typeof(EnemySlowWalker), "RotationLogic")]
		private static class WalkerAim
		{
			private static bool Prefix(EnemySlowWalker __instance)
			{
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				//IL_0008: Invalid comparison between Unknown and I4
				//IL_0015: Unknown result type (might be due to invalid IL or missing references)
				//IL_001c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0021: Unknown result type (might be due to invalid IL or missing references)
				//IL_0026: Unknown result type (might be due to invalid IL or missing references)
				//IL_006e: 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_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_0052: Unknown result type (might be due to invalid IL or missing references)
				if (!FocusPoint((MonoBehaviour)(object)__instance, (int)__instance.currentState == 7, out var point))
				{
					return true;
				}
				Vector3 val = point - ((Component)__instance).transform.position;
				val.y = 0f;
				if (((Vector3)(ref val)).sqrMagnitude > 0.01f)
				{
					WalkerRotation.Invoke(__instance) = Quaternion.LookRotation(val);
				}
				((Component)__instance).transform.rotation = SemiFunc.SpringQuaternionGet(__instance.horizontalRotationSpring, WalkerRotation.Invoke(__instance), -1f);
				return false;
			}
		}

		[HarmonyPatch(typeof(EnemyBowtie), "HorizontalRotationLogic")]
		private static class BowtieAim
		{
			private static bool Prefix(EnemyBowtie __instance)
			{
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				//IL_0008: Invalid comparison between Unknown and I4
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0011: Invalid comparison between Unknown and I4
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				//IL_001a: Invalid comparison between Unknown and I4
				//IL_002a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0031: Unknown result type (might be due to invalid IL or missing references)
				//IL_0036: Unknown result type (might be due to invalid IL or missing references)
				//IL_003b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0083: Unknown result type (might be due to invalid IL or missing references)
				//IL_008d: Unknown result type (might be due to invalid IL or missing references)
				//IL_009d: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a4: 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_0061: Unknown result type (might be due to invalid IL or missing references)
				//IL_0062: Unknown result type (might be due to invalid IL or missing references)
				//IL_0067: Unknown result type (might be due to invalid IL or missing references)
				//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d3: 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_00ea: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
				if (!FocusPoint((MonoBehaviour)(object)__instance, (int)__instance.currentState == 4 || (int)__instance.currentState == 5 || (int)__instance.currentState == 6, out var point))
				{
					return true;
				}
				Vector3 val = point - ((Component)__instance).transform.position;
				val.y = 0f;
				if (((Vector3)(ref val)).sqrMagnitude > 0.01f)
				{
					BowtieRotation.Invoke(__instance) = Quaternion.LookRotation(val);
				}
				((Component)__instance).transform.rotation = SemiFunc.SpringQuaternionGet(__instance.horizontalRotationSpring, BowtieRotation.Invoke(__instance), -1f);
				Vector3 val2 = ((Component)__instance).transform.InverseTransformDirection(point - __instance.verticalRotationTransform.position);
				if (((Vector3)(ref val2)).sqrMagnitude > 0.01f)
				{
					ref Quaternion reference = ref BowtieVertical.Invoke(__instance);
					Quaternion val3 = Quaternion.LookRotation(val2);
					reference = Quaternion.Euler(((Quaternion)(ref val3)).eulerAngles.x, 0f, 0f);
				}
				return false;
			}
		}

		[HarmonyPatch(typeof(EnemyBowtie), "VerticalRotationLogic")]
		private static class BowtieVerticalAim
		{
			private static bool Prefix(EnemyBowtie __instance)
			{
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				//IL_0008: Invalid comparison between Unknown and I4
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0011: Invalid comparison between Unknown and I4
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				//IL_001a: Invalid comparison between Unknown and I4
				//IL_0041: Unknown result type (might be due to invalid IL or missing references)
				//IL_004b: Unknown result type (might be due to invalid IL or missing references)
				if (!FocusPoint((MonoBehaviour)(object)__instance, (int)__instance.currentState == 4 || (int)__instance.currentState == 5 || (int)__instance.currentState == 6, out var _))
				{
					return true;
				}
				__instance.verticalRotationTransform.localRotation = SemiFunc.SpringQuaternionGet(__instance.verticalRotationSpring, BowtieVertical.Invoke(__instance), -1f);
				return false;
			}
		}

		[HarmonyPatch(typeof(EnemyTumbler), "RotationLogic")]
		private static class TumblerAim
		{
			private static bool Prefix(EnemyTumbler __instance)
			{
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				//IL_0008: Invalid comparison between Unknown and I4
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0011: Invalid comparison between Unknown and I4
				//IL_0021: Unknown result type (might be due to invalid IL or missing references)
				//IL_0028: Unknown result type (might be due to invalid IL or missing references)
				//IL_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_007a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0084: Unknown result type (might be due to invalid IL or missing references)
				//IL_0058: Unknown result type (might be due to invalid IL or missing references)
				//IL_0059: Unknown result type (might be due to invalid IL or missing references)
				//IL_005e: Unknown result type (might be due to invalid IL or missing references)
				if (!FocusPoint((MonoBehaviour)(object)__instance, (int)__instance.currentState == 6 || (int)__instance.currentState == 7, out var point))
				{
					return true;
				}
				Vector3 val = point - ((Component)__instance).transform.position;
				val.y = 0f;
				if (((Vector3)(ref val)).sqrMagnitude > 0.01f)
				{
					TumbleRotation.Invoke(__instance) = Quaternion.LookRotation(val);
				}
				((Component)__instance).transform.rotation = SemiFunc.SpringQuaternionGet(__instance.mainMeshSpring, TumbleRotation.Invoke(__instance), -1f);
				return false;
			}
		}

		[HarmonyPatch(typeof(EnemyTumbler), "StateTumble")]
		private static class TumblerLaunch
		{
			private static void Prefix(EnemyTumbler __instance)
			{
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				//IL_0008: Invalid comparison between Unknown and I4
				//IL_0061: 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_0078: Unknown result type (might be due to invalid IL or missing references)
				//IL_007d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0082: Unknown result type (might be due to invalid IL or missing references)
				//IL_008c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0091: Unknown result type (might be due to invalid IL or missing references)
				//IL_0095: Unknown result type (might be due to invalid IL or missing references)
				//IL_009a: 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_00ad: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ca: 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)
				if (FocusPoint((MonoBehaviour)(object)__instance, (int)__instance.currentState == 7, out var point) && TumbleImpulse.Invoke(__instance))
				{
					Enemy component = ((Component)__instance).GetComponent<Enemy>();
					TumbleImpulse.Invoke(__instance) = false;
					TumbleTimer.Invoke(__instance) = 1f;
					EnemyRigidbody val = Body.Invoke(component);
					EnemyNavMeshAgent component2 = ((Component)component).GetComponent<EnemyNavMeshAgent>();
					component2.Warp(((Component)val).transform.position, false);
					component2.ResetPath();
					Vector3 val2 = Vector3.Lerp(point - ((Component)val).transform.position, Vector3.up, 0.6f);
					Vector3 normalized = ((Vector3)(ref val2)).normalized;
					PhysicsBody.Invoke(val).AddForce(normalized * 40f, (ForceMode)1);
					PhysicsBody.Invoke(val).AddTorque(((Component)val).transform.right * 8f, (ForceMode)1);
				}
			}
		}

		private static readonly ConditionalWeakTable<MonoBehaviour, Focus> Focuses = new ConditionalWeakTable<MonoBehaviour, Focus>();

		private static readonly FieldRef<EnemyBeamer, Vector3> BeamerPoint = AccessTools.FieldRefAccess<EnemyBeamer, Vector3>("meleeTarget");

		private static readonly FieldRef<EnemyBeamer, bool> BeamerPlayer = AccessTools.FieldRefAccess<EnemyBeamer, bool>("meleePlayer");

		private static readonly FieldRef<EnemyTumbler, bool> TumbleImpulse = AccessTools.FieldRefAccess<EnemyTumbler, bool>("stateImpulse");

		private static readonly FieldRef<EnemyTumbler, float> TumbleTimer = AccessTools.FieldRefAccess<EnemyTumbler, float>("stateTimer");

		private static readonly FieldRef<Enemy, EnemyRigidbody> Body = AccessTools.FieldRefAccess<Enemy, EnemyRigidbody>("Rigidbody");

		private static readonly FieldRef<EnemyRigidbody, Rigidbody> PhysicsBody = AccessTools.FieldRefAccess<EnemyRigidbody, Rigidbody>("rb");

		private static readonly FieldRef<EnemyTumbler, Quaternion> TumbleRotation = AccessTools.FieldRefAccess<EnemyTumbler, Quaternion>("mainMeshTargetRotation");

		private static readonly FieldRef<EnemyBowtie, Quaternion> BowtieRotation = AccessTools.FieldRefAccess<EnemyBowtie, Quaternion>("horizontalRotationTarget");

		private static readonly FieldRef<EnemyBowtie, Quaternion> BowtieVertical = AccessTools.FieldRefAccess<EnemyBowtie, Quaternion>("verticalRotationTarget");

		private static readonly FieldRef<EnemySlowWalker, Quaternion> WalkerRotation = AccessTools.FieldRefAccess<EnemySlowWalker, Quaternion>("rotationTarget");

		private static void State(MonoBehaviour controller, object state)
		{
			AccessTools.Method(((object)controller).GetType(), "UpdateState", (Type[])null, (Type[])null).Invoke(controller, new object[1] { state });
		}

		private static void Remember(MonoBehaviour controller, Vector3 point)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			Focus value = Focuses.GetValue(controller, (MonoBehaviour _) => new Focus());
			value.Point = point;
			value.Until = Time.time + 16f;
		}

		private static bool FocusPoint(MonoBehaviour controller, bool attacking, out Vector3 point)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: 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)
			point = default(Vector3);
			if (!SemiFunc.IsMasterClientOrSingleplayer() || !Focuses.TryGetValue(controller, out Focus value))
			{
				return false;
			}
			if (!attacking || Time.time >= value.Until || !((Behaviour)controller).isActiveAndEnabled)
			{
				Focuses.Remove(controller);
				return false;
			}
			point = value.Point;
			return true;
		}

		internal static bool TryStart(Enemy enemy, Vector3 point)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			EnemySlowWalker component = ((Component)enemy).GetComponent<EnemySlowWalker>();
			if (Object.op_Implicit((Object)(object)component) && ((Behaviour)component).isActiveAndEnabled && EchoEnemyReactionPolicy.CanInvestigate(((object)Unsafe.As<State, State>(ref component.currentState)/*cast due to .constrained prefix*/).ToString()))
			{
				Remember((MonoBehaviour)(object)component, point);
				State((MonoBehaviour)(object)component, (object)(State)7);
				return true;
			}
			EnemyBeamer component2 = ((Component)enemy).GetComponent<EnemyBeamer>();
			if (Object.op_Implicit((Object)(object)component2) && ((Behaviour)component2).isActiveAndEnabled && EchoEnemyReactionPolicy.CanInvestigate(((object)Unsafe.As<State, State>(ref component2.currentState)/*cast due to .constrained prefix*/).ToString()))
			{
				BeamerPoint.Invoke(component2) = point;
				BeamerPlayer.Invoke(component2) = false;
				State((MonoBehaviour)(object)component2, (object)(State)7);
				return true;
			}
			EnemyFloater component3 = ((Component)enemy).GetComponent<EnemyFloater>();
			if (Object.op_Implicit((Object)(object)component3) && ((Behaviour)component3).isActiveAndEnabled && EchoEnemyReactionPolicy.CanInvestigate(((object)Unsafe.As<State, State>(ref component3.currentState)/*cast due to .constrained prefix*/).ToString()))
			{
				State((MonoBehaviour)(object)component3, (object)(State)7);
				return true;
			}
			EnemyBowtie component4 = ((Component)enemy).GetComponent<EnemyBowtie>();
			if (Object.op_Implicit((Object)(object)component4) && ((Behaviour)component4).isActiveAndEnabled && EchoEnemyReactionPolicy.CanInvestigate(((object)Unsafe.As<State, State>(ref component4.currentState)/*cast due to .constrained prefix*/).ToString()))
			{
				Remember((MonoBehaviour)(object)component4, point);
				State((MonoBehaviour)(object)component4, (object)(State)4);
				return true;
			}
			EnemyTumbler component5 = ((Component)enemy).GetComponent<EnemyTumbler>();
			if (Object.op_Implicit((Object)(object)component5) && ((Behaviour)component5).isActiveAndEnabled && EchoEnemyReactionPolicy.CanInvestigate(((object)Unsafe.As<State, State>(ref component5.currentState)/*cast due to .constrained prefix*/).ToString()))
			{
				Remember((MonoBehaviour)(object)component5, point);
				State((MonoBehaviour)(object)component5, (object)(State)6);
				return true;
			}
			return false;
		}
	}
	public sealed class EchoBehaviourPolicy
	{
		public enum Intent
		{
			Roaming,
			Inspecting,
			Company
		}

		public const float RoamSeconds = 18f;

		public const float InspectionSeconds = 1.5f;

		public const float CompanySeconds = 3f;

		private float companyCooldown;

		public Intent Current { get; private set; }

		public float Remaining { get; private set; }

		public EchoBehaviourPolicy()
		{
			Reset();
		}

		public void Reset()
		{
			Current = Intent.Roaming;
			Remaining = 18f;
			companyCooldown = 18f;
		}

		public bool Step(float dt, bool companionNearby, bool arrived, bool routeFailed)
		{
			if (float.IsNaN(dt) || float.IsInfinity(dt) || dt < 0f)
			{
				dt = 0f;
			}
			Remaining -= dt;
			companyCooldown = Math.Max(0f, companyCooldown - dt);
			switch (Current)
			{
			case Intent.Roaming:
				if (routeFailed)
				{
					Reset();
					return true;
				}
				if (arrived)
				{
					Current = Intent.Inspecting;
					Remaining = 1.5f;
					return true;
				}
				if (Remaining > 0f)
				{
					return false;
				}
				break;
			case Intent.Inspecting:
				if (Remaining > 0f)
				{
					return false;
				}
				break;
			case Intent.Company:
				if (Remaining > 0f && companionNearby && !routeFailed)
				{
					return false;
				}
				Reset();
				return true;
			}
			if (companionNearby && companyCooldown <= 0f)
			{
				Current = Intent.Company;
				Remaining = 3f;
			}
			else
			{
				Current = Intent.Roaming;
				Remaining = 18f;
			}
			return true;
		}

		public static float FriendlyDelay(float configuredSeconds, float intervalScale, float variation)
		{
			return Math.Max(8f, (Math.Max(0f, configuredSeconds) + Math.Max(0f, variation)) * Math.Max(0f, intervalScale));
		}

		public static bool NeedsEscapeReplan(bool hasRoute, bool arrived, bool blocked, bool invalidPath, bool progressSampleDue, float progressMetres)
		{
			if (!(!hasRoute || arrived || blocked || invalidPath))
			{
				if (progressSampleDue)
				{
					return progressMetres < 0.3f;
				}
				return false;
			}
			return true;
		}

		public static float EscapeScore(float travel, float threatDistance, float awayDot, bool repeatsFailedRoute)
		{
			if (!(travel < 0.65f))
			{
				return threatDistance + Math.Min(travel, 6f) * 0.3f + awayDot * 2f - (float)(repeatsFailedRoute ? 12 : 0);
			}
			return float.NegativeInfinity;
		}

		public static float RouteScore(float length, float startDistance, float endDistance, float closestPass, float firstStepAway, bool concealed, float clearance, bool repeatsFailedRoute, bool exitsRoom = false)
		{
			if (length < 1f)
			{
				return float.NegativeInfinity;
			}
			if (exitsRoom)
			{
				return 1000f - length * 3f + (float)(concealed ? 12 : 0) + Math.Min(clearance, 2f) - Math.Max(0f, 1f - closestPass) * 4f - (float)(repeatsFailedRoute ? 500 : 0);
			}
			if (startDistance > 2.5f && closestPass < 1.7f)
			{
				return float.NegativeInfinity;
			}
			return endDistance * 1.5f + (endDistance - startDistance) + Math.Min(length, 10f) * 0.15f - Math.Max(0f, length - endDistance - startDistance) * 0.6f + firstStepAway * 3f + (float)(concealed ? 7 : 0) + Math.Min(clearance, 2f) - Math.Max(0f, startDistance - closestPass) * 3f - (float)(repeatsFailedRoute ? 18 : 0);
		}
	}
	public sealed class EchoOriginalEncounterPolicy
	{
		public const float GraceSeconds = 2f;

		public const float ExposureSeconds = 0.4f;

		private float eligibleAt;

		private float exposedFor;

		private bool encountered;

		public static bool SharesRoom<T>(IReadOnlyList<T>? echoRooms, IReadOnlyList<T>? originalRooms) where T : class
		{
			if (echoRooms == null || originalRooms == null)
			{
				return false;
			}
			foreach (T echoRoom in echoRooms)
			{
				if (echoRoom == null)
				{
					continue;
				}
				foreach (T originalRoom in originalRooms)
				{
					if (echoRoom == originalRoom)
					{
						return true;
					}
				}
			}
			return false;
		}

		public void Reset(float now)
		{
			eligibleAt = now + 2f;
			exposedFor = 0f;
			encountered = false;
		}

		public void SuspendExposure()
		{
			exposedFor = 0f;
		}

		public bool Observe(float now, float dt, bool eligible, bool originalVisible, int activePlayers)
		{
			if (!originalVisible || activePlayers < 1)
			{
				exposedFor = 0f;
				if (encountered)
				{
					encountered = false;
					eligibleAt = Math.Max(eligibleAt, now + 2f);
				}
				return false;
			}
			if (!eligible || now < eligibleAt)
			{
				exposedFor = 0f;
				return false;
			}
			if (!float.IsNaN(dt) && !float.IsInfinity(dt))
			{
				exposedFor += Math.Max(0f, dt);
			}
			if (exposedFor < 0.4f)
			{
				return false;
			}
			encountered = true;
			exposedFor = 0f;
			eligibleAt = now + 8f;
			return true;
		}
	}
	internal static class EchoCartApproach
	{
		internal static bool BoundsOf(PhysGrabCart cart, out Bounds bounds)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			Rigidbody body = ((Component)cart).GetComponent<Rigidbody>();
			Collider[] array = (from c in ((Component)cart).GetComponentsInChildren<Collider>()
				where c.enabled && !c.isTrigger && (Object)(object)c.attachedRigidbody == (Object)(object)body
				select c).ToArray();
			bounds = default(Bounds);
			if (array.Length == 0)
			{
				return false;
			}
			bounds = array[0].bounds;
			Collider[] array2 = array;
			foreach (Collider val in array2)
			{
				((Bounds)(ref bounds)).Encapsulate(val.bounds);
			}
			return true;
		}

		internal static bool HandlePosition(EchoMotor motor, PhysGrabCart cart, out Vector3 goal)
		{
			//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_004f: 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_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: 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_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: 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_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: 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_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: 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_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: 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_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			goal = ((Component)motor).transform.position;
			if (!BoundsOf(cart, out var bounds))
			{
				return false;
			}
			Vector3 val = (Object.op_Implicit((Object)(object)cart.cartGrabPoint) ? cart.cartGrabPoint.position : cart.handlePoint.position);
			Vector3 val2 = val - ((Bounds)(ref bounds)).center;
			val2.y = 0f;
			if (((Vector3)(ref val2)).sqrMagnitude < 0.01f)
			{
				val2 = -((Component)cart).transform.forward;
			}
			((Vector3)(ref val2)).Normalize();
			float num = Mathf.Abs(val2.x) * ((Bounds)(ref bounds)).extents.x + Mathf.Abs(val2.z) * ((Bounds)(ref bounds)).extents.z;
			Vector3 val3 = ((Bounds)(ref bounds)).center + val2 * (num + 0.8f);
			val3.y = ((Component)motor).transform.position.y;
			NavMeshHit val4 = default(NavMeshHit);
			if (!NavMesh.SamplePosition(val3, ref val4, 0.4f, -1) || Mathf.Abs(((NavMeshHit)(ref val4)).position.y - val3.y) > 0.4f)
			{
				return false;
			}
			if (Physics.OverlapCapsule(((NavMeshHit)(ref val4)).position + Vector3.up * 0.4f, ((NavMeshHit)(ref val4)).position + Vector3.up * 1.45f, 0.32f, EchoMotor.SolidMask, (QueryTriggerInteraction)1).Any((Collider c) => !((Component)c).transform.IsChildOf(((Component)motor).transform)))
			{
				return false;
			}
			if (Vector3.Distance(((NavMeshHit)(ref val4)).position + Vector3.up, val) > 3.5f)
			{
				return false;
			}
			goal = ((NavMeshHit)(ref val4)).position;
			return true;
		}

		internal static List<Vector3>? Find(EchoMotor motor, PhysGrabCart cart, Vector3 goal)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: 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_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: 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)
			if (!BoundsOf(cart, out var bounds))
			{
				return null;
			}
			List<Vector3> nodes = new List<Vector3>
			{
				((Component)motor).transform.position,
				goal
			};
			Vector3 center = ((Bounds)(ref bounds)).center;
			center.y = goal.y;
			int[] array = new int[3] { -1, 0, 1 };
			NavMeshHit val = default(NavMeshHit);
			foreach (int num in array)
			{
				int[] array2 = new int[3] { -1, 0, 1 };
				foreach (int num2 in array2)
				{
					if ((num != 0 || num2 != 0) && NavMesh.SamplePosition(center + new Vector3((float)num * (((Bounds)(ref bounds)).extents.x + 0.65f), 0f, (float)num2 * (((Bounds)(ref bounds)).extents.z + 0.65f)), ref val, 0.35f, -1))
					{
						nodes.Add(((NavMeshHit)(ref val)).position);
					}
				}
			}
			float[,] array3 = new float[nodes.Count, nodes.Count];
			for (int k = 0; k < nodes.Count; k++)
			{
				for (int l = 0; l < nodes.Count; l++)
				{
					array3[k, l] = ((k == l) ? 0f : (Clear(nodes[k], nodes[l]) ? Vector3.Distance(nodes[k], nodes[l]) : float.PositiveInfinity));
				}
			}
			return CartApproachPath.Find(array3)?.Select((int index) => nodes[index]).ToList();
			bool Clear(Vector3 a, Vector3 b)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0012: Unknown result type (might be due to invalid IL or missing references)
				//IL_0013: Unknown result type (might be due to invalid IL or missing references)
				NavMeshHit val2 = default(NavMeshHit);
				if (!NavMesh.Raycast(a, b, ref val2, -1))
				{
					return motor.Clear(a, b, null);
				}
				return false;
			}
		}
	}
	[DefaultExecutionOrder(12000)]
	public sealed class EchoCartBeam : MonoBehaviour
	{
		private EchoController brain;

		private EchoAppearance appearance;

		private LineRenderer? line;

		private Material? material;

		public bool Visible
		{
			get
			{
				if (Object.op_Implicit((Object)(object)line))
				{
					return ((Renderer)line).enabled;
				}
				return false;
			}
		}

		private void Awake()
		{
			brain = ((Component)this).GetComponent<EchoController>();
			appearance = ((Component)this).GetComponent<EchoAppearance>();
		}

		private void LateUpdate()
		{
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: 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_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Expected O, but got Unknown
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Expected O, but got Unknown
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			if (!brain.CartGripping || !Object.op_Implicit((Object)(object)appearance.GripOrigin) || ((Component)this).GetComponent<EchoMotor>().IsTumbling)
			{
				if (Object.op_Implicit((Object)(object)line))
				{
					((Renderer)line).enabled = false;
				}
				return;
			}
			if (!Object.op_Implicit((Object)(object)line))
			{
				GameObject val = Resources.Load<GameObject>("PlayerAvatar");
				PhysGrabBeam val2 = (Object.op_Implicit((Object)(object)val) ? val.GetComponentInChildren<PhysGrabBeam>(true) : null);
				if (!Object.op_Implicit((Object)(object)val2) || !Object.op_Implicit((Object)(object)val2.lineRenderer))
				{
					return;
				}
				GameObject val3 = new GameObject("Echo cart grab beam");
				val3.transform.SetParent(((Component)this).transform, false);
				line = val3.AddComponent<LineRenderer>();
				material = new Material(((Renderer)val2.lineRenderer).sharedMaterial);
				((Renderer)line).sharedMaterial = material;
				line.widthCurve = val2.lineRenderer.widthCurve;
				line.widthMultiplier = val2.lineRenderer.widthMultiplier;
				line.colorGradient = val2.lineRenderer.colorGradient;
				line.textureMode = val2.lineRenderer.textureMode;
				line.alignment = (LineAlignment)0;
				((Renderer)line).shadowCastingMode = (ShadowCastingMode)0;
				((Renderer)line).receiveShadows = false;
				line.useWorldSpace = true;
				line.positionCount = 20;
			}
			((Renderer)line).enabled = true;
			Vector3 position = appearance.GripOrigin.position;
			Vector3 cartGripPoint = brain.CartGripPoint;
			for (int i = 0; i < 20; i++)
			{
				float num = (float)i / 19f;
				line.SetPosition(i, Vector3.Lerp(position, cartGripPoint, num) + Vector3.up * (Mathf.Sin(num * MathF.PI) * 0.06f));
			}
			if (Object.op_Implicit((Object)(object)material))
			{
				material.mainTextureOffset = new Vector2((0f - Time.time) * 5f, 0f);
			}
		}

		private void OnDisable()
		{
			if (Object.op_Implicit((Object)(object)line))
			{
				((Renderer)line).enabled = false;
			}
		}

		private void OnDestroy()
		{
			if (Object.op_Implicit((Object)(object)material))
			{
				Object.Destroy((Object)(object)material);
			}
			if (Object.op_Implicit((Object)(object)line))
			{
				Object.Destroy((Object)(object)((Component)line).gameObject);
			}
		}
	}
	public sealed class EchoCartTheft : MonoBehaviour
	{
		private static readonly Dictionary<PhysGrabCart, EchoCartTheft> Claims = new Dictionary<PhysGrabCart, EchoCartTheft>();

		private static readonly FieldRef<PhysGrabCart, int> Haul = AccessTools.FieldRefAccess<PhysGrabCart, int>("haulCurrent");

		private static readonly FieldRef<PhysGrabCart, int> Count = AccessTools.FieldRefAccess<PhysGrabCart, int>("itemsInCartCount");

		private static readonly FieldRef<PlayerAvatar, bool> Disabled = AccessTools.FieldRefAccess<PlayerAvatar, bool>("isDisabled");

		private static readonly FieldRef<EnemyHealth, bool> Dead = AccessTools.FieldRefAccess<EnemyHealth, bool>("dead");

		private static readonly FieldRef<PhysGrabObject, bool> Frozen = AccessTools.FieldRefAccess<PhysGrabObject, bool>("frozen");

		private static readonly FieldRef<PhysGrabCart, bool> ActiveCart = AccessTools.FieldRefAccess<PhysGrabCart, bool>("cartActive");

		private static readonly FieldRef<PhysGrabCart, bool> Pulled = AccessTools.FieldRefAccess<PhysGrabCart, bool>("cartBeingPulled");

		private static readonly FieldRef<PhysGrabCart, List<PhysGrabObject>> Cargo = AccessTools.FieldRefAccess<PhysGrabCart, List<PhysGrabObject>>("itemsInCart");

		private static readonly FieldRef<PhysGrabObject, float> MassTimer = AccessTools.FieldRefAccess<PhysGrabObject, float>("timerAlterMass");

		private static readonly FieldRef<PhysGrabObject, float> MassValue = AccessTools.FieldRefAccess<PhysGrabObject, float>("alterMassValue");

		private static readonly FieldRef<PhysGrabObject, float> DragTimer = AccessTools.FieldRefAccess<PhysGrabObject, float>("timerAlterDrag");

		private static readonly FieldRef<PhysGrabObject, float> DragValue = AccessTools.FieldRefAccess<PhysGrabObject, float>("alterDragValue");

		private static readonly FieldRef<PhysGrabObject, float> AngularDragTimer = AccessTools.FieldRefAccess<PhysGrabObject, float>("timerAlterAngularDrag");

		private static readonly FieldRef<PhysGrabObject, float> AngularDragValue = AccessTools.FieldRefAccess<PhysGrabObject, float>("alterAngularDragValue");

		private static readonly FieldRef<RoomVolumeCheck, bool> InTruck = AccessTools.FieldRefAccess<RoomVolumeCheck, bool>("inTruck");

		private EchoMotor motor;

		private EnemyHealth health;

		private NavMeshAgent agent;

		private EchoController brain;

		private Enemy enemy;

		private PhysGrabCart? cart;

		private PhysGrabObject? item;

		private Rigidbody? body;

		private readonly CartMischiefCycle cycle = new CartMischiefCycle();

		private readonly CartTheftProgress progress = new CartTheftProgress();

		private float nextTry;

		private float expires;

		private float routeAt;

		private float approachAt;

		private float arrivedAt;

		private float replanAt;

		private float gripDistance = 2.6f;

		private bool forced;

		private bool pulling;

		private bool physicallyBlocked;

		private Vector3 route;

		private Vector3 cartRoute;

		private Vector3 approach;

		private Vector3 approachCartPosition;

		private Vector3 driveDirection;

		private Quaternion approachCartRotation;

		private List<Vector3>? approachPath;

		private PlayerAvatar? retaliation;

		private PlayerAvatar? companionAtGrab;

		public CartMischiefCycle.Stage Stage => cycle.Current;

		public bool IsHolding
		{
			get
			{
				if (Object.op_Implicit((Object)(object)cart))
				{
					return cycle.Current >= CartMischiefCycle.Stage.Helping;
				}
				return false;
			}
		}

		public PhysGrabCart? Cart => cart;

		public int TheftStarts { get; private set; }

		public int HazardRoutes { get; private set; }

		public Vector3 Destination { get; private set; }

		public float Pace
		{
			get
			{
				//IL_0033: 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)
				if (Stage != CartMischiefCycle.Stage.Readying && !physicallyBlocked)
				{
					if (Stage != CartMischiefCycle.Stage.Stealing || !Object.op_Implicit((Object)(object)body))
					{
						return 1.6f;
					}
					return CartTheftMotion.LeaderPace(Flat(body.position, ((Component)this).transform.position));
				}
				return 0f;
			}
		}

		public Vector3 GrabPoint
		{
			get
			{
				//IL_0025: Unknown result type (might be due to invalid IL or missing references)
				//IL_0036: Unknown result type (might be due to invalid IL or missing references)
				if (!Object.op_Implicit((Object)(object)cart) || !Object.op_Implicit((Object)(object)cart.cartGrabPoint))
				{
					return ((Component)this).transform.position;
				}
				return cart.cartGrabPoint.position;
			}
		}

		public Vector3 LookAt
		{
			get
			{
				//IL_0015: Unknown result type (might be due to invalid IL or missing references)
				//IL_0009: Unknown result type (might be due to invalid IL or missing references)
				//IL_005c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0062: Unknown result type (might be due to invalid IL or missing references)
				//IL_0067: 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_007b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0080: Unknown result type (might be due to invalid IL or missing references)
				if (!IsHolding)
				{
					return GrabPoint;
				}
				return ((Component)this).transform.position + Quaternion.Euler(0f, (Stage == CartMischiefCycle.Stage.Readying) ? (Mathf.Sin((1.2f - cycle.Remaining) * MathF.PI / 0.6f) * 65f) : 0f, 0f) * driveDirection * 5f + Vector3.up;
			}
		}

		public int CartViewId
		{
			get
			{
				if (!IsHolding || !Object.op_Implicit((Object)(object)cart))
				{
					return -1;
				}
				return ((Component)cart).GetComponent<PhotonView>().ViewID;
			}
		}

		private bool Loaded
		{
			get
			{
				if (Object.op_Implicit((Object)(object)cart))
				{
					if (Count.Invoke(cart) <= 0)
					{
						return Haul.Invoke(cart) > 0;
					}
					return true;
				}
				return false;
			}
		}

		private void Awake()
		{
			motor = ((Component)this).GetComponent<EchoMotor>();
			health = ((Component)this).GetComponent<EnemyHealth>();
			agent = ((Component)this).GetComponent<NavMeshAgent>();
			brain = ((Component)this).GetComponent<EchoController>();
			enemy = ((Component)this).GetComponent<Enemy>();
		}

		private void OnEnable()
		{
			nextTry = Time.time + Random.Range(25f, 40f);
			SceneManager.activeSceneChanged += SceneChanged;
		}

		private void SceneChanged(Scene previous, Scene next)
		{
			Release("scene changed");
			retaliation = null;
		}

		public static bool Holding(PhysGrabCart c)
		{
			if (Object.op_Implicit((Object)(object)c) && Claims.TryGetValue(c, out EchoCartTheft value) && Object.op_Implicit((Object)(object)value) && ((Behaviour)value).isActiveAndEnabled && value.IsHolding && SemiFunc.IsMasterClientOrSingleplayer() && !value.motor.IsTumbling && !Dead.Invoke(value.health))
			{
				return !Object.op_Implicit((Object)(object)value.PlayerHolder());
			}
			return false;
		}

		private static bool Usable(PhysGrabCart c)
		{
			if (!Object.op_Implicit((Object)(object)c) || !((Behaviour)c).isActiveAndEnabled || c.isSmallCart)
			{
				return false;
			}
			PhysGrabObject component = ((Component)c).GetComponent<PhysGrabObject>();
			Rigidbody component2 = ((Component)c).GetComponent<Rigidbody>();
			RoomVolumeCheck component3 = ((Component)c).GetComponent<RoomVolumeCheck>();
			if (Object.op_Implicit((Object)(object)component) && ((Behaviour)component).isActiveAndEnabled && component.spawned && !component.dead && !Frozen.Invoke(component) && Object.op_Implicit((Object)(object)component2) && !component2.isKinematic)
			{
				if (Object.op_Implicit((Object)(object)component3))
				{
					return !InTruck.Invoke(component3);
				}
				return true;
			}
			return false;
		}

		public string TestStart(bool ignoreWatching = true)
		{
			if (!SemiFunc.IsMasterClientOrSingleplayer())
			{
				return "Only the host can test Echo's cart theft.";
			}
			if (motor.IsTumbling)
			{
				return "Let Echo stand up first.";
			}
			Release();
			forced = ignoreWatching;
			if (!TryStart())
			{
				forced = false;
				return "No reachable loaded, unattended cart nearby. Put valuables in a cart outside the truck.";
			}
			return "Echo cart test: approach, help briefly, prepare, then steal. " + (ignoreWatching ? "This demonstration ignores watching; " : "Prefers an unwatched opening; ") + "Q or grabbing the cart interrupts.";
		}

		private bool TryStart()
		{
			//IL_0095: 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_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: Unknown result type (might be due to invalid IL or missing references)
			//IL_0215: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_0226: Unknown result type (might be due to invalid IL or missing references)
			foreach (PhysGrabCart item in (from c in Object.FindObjectsOfType<PhysGrabCart>().Where(Usable)
				orderby Haul.Invoke(c) >= EnemyMod.CartLootMinimum.Value descending
				select c).ThenBy(delegate(PhysGrabCart c)
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_0011: Unknown result type (might be due to invalid IL or missing references)
				//IL_0016: Unknown result type (might be due to invalid IL or missing references)
				//IL_001b: Unknown result type (might be due to invalid IL or missing references)
				Vector3 val = ((Component)c).transform.position - ((Component)this).transform.position;
				return ((Vector3)(ref val)).sqrMagnitude;
			}))
			{
				if ((Claims.TryGetValue(item, out EchoCartTheft value) && Object.op_Implicit((Object)(object)value) && (Object)(object)value != (Object)(object)this) || Vector3.Distance(((Component)this).transform.position, ((Component)item).transform.position) > 14f || (Haul.Invoke(item) <= 0 && Count.Invoke(item) <= 0))
				{
					continue;
				}
				PhysGrabObject component = ((Component)item).GetComponent<PhysGrabObject>();
				if (!component.playerGrabbing.Any((PhysGrabber p) => Object.op_Implicit((Object)(object)p) && Object.op_Implicit((Object)(object)p.playerAvatar) && !Disabled.Invoke(p.playerAvatar)) && EchoCartApproach.HandlePosition(motor, item, out approach) && Reachable(approach, out approach))
				{
					approachPath = EchoCartApproach.Find(motor, item, approach);
					if (approachPath != null)
					{
						cart = item;
						this.item = component;
						body = ((Component)item).GetComponent<Rigidbody>();
						Claims[cart] = this;
						cycle.Begin();
						expires = Time.time + 28f;
						Destination = approach;
						routeAt = (approachAt = (arrivedAt = (replanAt = 0f)));
						gripDistance = 2.6f;
						approachCartPosition = ((Component)item).transform.position;
						pulling = (physicallyBlocked = false);
						approachCartRotation = ((Component)item).transform.rotation;
						driveDirection = ((Component)item).transform.forward;
						driveDirection.y = 0f;
						((Vector3)(ref driveDirection)).Normalize();
						EnemyMod.Log.LogInfo((object)"Echo is approaching a loaded cart to help.");
						return true;
					}
				}
			}
			return false;
		}

		public bool Tick(PlayerAvatar companion, Vector3 groupVelocity, bool mayStart, bool interrupted)
		{
			//IL_0342: 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_034c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0352: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: 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_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0262: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_022d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0270: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: 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_02b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02da: Unknown result type (might be due to invalid IL or missing references)
			//IL_0540: Unknown result type (might be due to invalid IL or missing references)
			//IL_04aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ab: 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_045f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0310: Unknown result type (might be due to invalid IL or missing references)
			//IL_0558: Unknown result type (might be due to invalid IL or missing references)
			//IL_0568: Unknown result type (might be due to invalid IL or missing references)
			//IL_056e: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e1: 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_04f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f7: 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_050b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0510: Unknown result type (might be due to invalid IL or missing references)
			//IL_0678: Unknown result type (might be due to invalid IL or missing references)
			//IL_067e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0529: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_064b: Unknown result type (might be due to invalid IL or missing references)
			//IL_05e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_05fc: Unknown result type (might be due to invalid IL or missing references)
			if (!SemiFunc.IsMasterClientOrSingleplayer() || interrupted)
			{
				Release();
				return false;
			}
			if (!Object.op_Implicit((Object)(object)cart) && Stage != CartMischiefCycle.Stage.Idle)
			{
				Release();
				return false;
			}
			if (!Object.op_Implicit((Object)(object)cart))
			{
				if (!mayStart || !EnemyMod.CartSabotage.Value || Time.time < nextTry)
				{
					return false;
				}
				nextTry = Time.time + 10f;
				if (Random.value > 0.65f || !TryStart())
				{
					return false;
				}
			}
			if (companionAtGrab == null)
			{
				companionAtGrab = companion;
			}
			if (!Usable(cart) || !Object.op_Implicit((Object)(object)item) || !Object.op_Implicit((Object)(object)body) || Time.time > expires || !ValidCompanion())
			{
				Release("cart or companion unavailable, or time limit");
				return false;
			}
			PhysGrabber val = PlayerHolder();
			if (Object.op_Implicit((Object)(object)val))
			{
				bool num = Stage == CartMischiefCycle.Stage.Stealing;
				PlayerAvatar playerAvatar = val.playerAvatar;
				Release("real player reclaimed cart");
				if (num)
				{
					retaliation = playerAvatar;
				}
				return false;
			}
			if (Stage == CartMischiefCycle.Stage.Approaching)
			{
				if (Time.time >= approachAt && (Flat(approachCartPosition, ((Component)cart).transform.position) > 0.25f || Quaternion.Angle(approachCartRotation, ((Component)cart).transform.rotation) > 10f))
				{
					approachAt = Time.time + 0.5f;
					if (!EchoCartApproach.HandlePosition(motor, cart, out approach) || (approachPath = EchoCartApproach.Find(motor, cart, approach)) == null)
					{
						Release("moved cart has no clear handle approach");
						return false;
					}
					approachCartPosition = ((Component)cart).transform.position;
					approachCartRotation = ((Component)cart).transform.rotation;
				}
				if (approachPath != null && approachPath.Count > 1 && Flat(((Component)this).transform.position, approachPath[0]) < 0.6f)
				{
					approachPath.RemoveAt(0);
				}
				Destination = ((approachPath != null && approachPath.Count > 0) ? approachPath[0] : approach);
				cycle.Step(Time.deltaTime, loaded: false, unwatched: false, interrupted: false);
				if (cycle.Current == CartMischiefCycle.Stage.Idle)
				{
					Release();
					return false;
				}
				if (Flat(((Component)this).transform.position, approach) < 0.55f && Vector3.Distance(((Component)this).transform.position + Vector3.up, GrabPoint) < 3.6f && GripClear())
				{
					cycle.Hold();
					routeAt = 0f;
					Destination = ((Component)this).transform.position;
					expires = Time.time + 28f;
					EnemyMod.Log.LogInfo((object)"Echo took a physical cart grip; helping before betrayal.");
				}
				return true;
			}
			if (Vector3.Distance(((Component)this).transform.position + Vector3.up, GrabPoint) > 4.2f || !GripClear())
			{
				Release("grip out of reach or behind solid obstruction");
				return false;
			}
			bool flag = SemiFunc.PlayerGetList().Any((PlayerAvatar p) => Object.op_Implicit((Object)(object)p) && !Disabled.Invoke(p) && (brain.PlayerWatching(p, ((Component)cart).transform.position) || brain.PlayerWatching(p, ((Component)this).transform.position)));
			CartMischiefCycle.Stage stage = Stage;
			cycle.Step(Time.deltaTime, Loaded, forced || !flag, interrupted: false);
			if (Stage == CartMischiefCycle.Stage.Idle)
			{
				Release();
				return false;
			}
			if (Stage == CartMischiefCycle.Stage.Stealing && stage != Stage)
			{
				if (!PickTheftRoute(companion))
				{
					EnemyMod.Log.LogInfo((object)"Echo abandoned cart theft: no cart-width escape route.");
					Release();
					return false;
				}
				TheftStarts++;
				routeAt = Time.time + 10f;
				arrivedAt = 0f;
				replanAt = Time.time + 1f;
				progress.Begin(Flat(body.position, cartRoute));
				EnemyMod.Log.LogInfo((object)"Echo stole the cart: physical sprint, no launch/teleport.");
			}
			if (Stage == CartMischiefCycle.Stage.Helping && Time.time >= routeAt)
			{
				routeAt = Time.time + 1f;
				Vector3 direction = groupVelocity;
				direction.y = 0f;
				Vector3 point;
				if (((Vector3)(ref direction)).magnitude < 0.4f)
				{
					Destination = ((Component)this).transform.position;
				}
				else if (Reachable(((Component)this).transform.position + ((Vector3)(ref direction)).normalized * 2f, out point) && EchoHazards.Evaluate(body.position, direction).Score <= 0f)
				{
					Destination = point;
				}
			}
			if (Stage == CartMischiefCycle.Stage.Readying)
			{
				Destination = ((Component)this).transform.position;
			}
			if (Stage == CartMischiefCycle.Stage.Stealing)
			{
				Destination = route;
				if (Flat(((Component)this).transform.position, route) < 0.6f)
				{
					if (arrivedAt == 0f)
					{
						arrivedAt = Time.time;
					}
					if (Time.time - arrivedAt > 0.4f || Flat(body.position, cartRoute) < 0.8f)
					{
						if (!PickTheftRoute(companion))
						{
							Release("no safe continuation for cart");
							return false;
						}
						arrivedAt = 0f;
						Destination = route;
						progress.Begin(Flat(body.position, cartRoute));
					}
				}
				if (physicallyBlocked && Time.time >= replanAt)
				{
					replanAt = Time.time + 1f;
					if (PickTheftRoute(companion))
					{
						Destination = route;
						arrivedAt = 0f;
						physicallyBlocked = false;
					}
				}
				if (progress.ShouldRelease(Time.deltaTime, Flat(body.position, cartRoute), physicallyBlocked))
				{
					Release("cart made no progress or its physical route is blocked");
					return false;
				}
			}
			return true;
		}

		public PlayerAvatar? TakeRetaliation()
		{
			PlayerAvatar? result = retaliation;
			retaliation = null;
			return result;
		}

		public bool EscapeWithCart(PlayerAvatar pursuer)
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			if (!IsHolding || !Loaded || !Object.op_Implicit((Object)(object)body) || Object.op_Implicit((Object)(object)PlayerHolder()) || !PickTheftRoute(pursuer))
			{
				return false;
			}
			cycle.Steal();
			TheftStarts++;
			companionAtGrab = pursuer;
			Destination = route;
			arrivedAt = 0f;
			replanAt = Time.time + 1f;
			progress.Begin(Flat(body.position, cartRoute));
			EnemyMod.Log.LogInfo((object)"Echo recognized while holding cart: escaping with the haul.");
			return true;
		}

		private bool PickTheftRoute(PlayerAvatar companion)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0304: Unknown result type (might be due to invalid IL or missing references)
			//IL_0309: 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_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: 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_0367: Unknown result type (might be due to invalid IL or missing references)
			//IL_0372: Unknown result type (might be due to invalid IL or missing references)
			//IL_0387: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: 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_00ed: 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_0103: 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_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: 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_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: 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_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: 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_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01de: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: Unknown result type (might be due to invalid IL or missing references)
			//IL_0232: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: 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)
			//IL_028f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0298: Unknown result type (might be due to invalid IL or missing references)
			//IL_0299: Unknown result type (might be due to invalid IL or missing references)
			//IL_0295: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02be: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c0: Unknown result type (might be due to invalid IL or missing references)
			float num = float.NegativeInfinity;
			bool flag = false;
			bool flag2 = false;
			Vector3 val = ((Component)this).transform.position - body.position;
			val.y = 0f;
			((Vector3)(ref val)).Normalize();
			float[] array = new float[4] { 2f, 3.5f, 5f, 8f };
			NavMeshHit val3 = default(NavMeshHit);
			foreach (float num2 in array)
			{
				for (int j = 0; j < 12; j++)
				{
					Vector3 val2 = Quaternion.Euler(0f, (float)(j * 30), 0f) * driveDirection;
					if (!Reachable(((Component)this).transform.position + val2 * num2, out var point) || Flat(point, ((Component)this).transform.position) < 1.5f)
					{
						continue;
					}
					EchoHazards.Push push = EchoHazards.Evaluate(point, val2);
					bool flag3 = push.Score > 0f;
					if ((!flag3 && Vector3.Dot(val2, val) < 0.15f) || (flag3 && Vector3.Dot(val2, -val) < 0.5f))
					{
						continue;
					}
					Vector3 point2 = (flag3 ? (push.Edge - val2 * 1.6f) : point);
					if (!Reachable(point2, out point2) || Flat(point2, ((Component)this).transform.position) < 1.5f)
					{
						continue;
					}
					val2 = point2 - ((Component)this).transform.position;
					val2.y = 0f;
					((Vector3)(ref val2)).Normalize();
					if (Vector3.Dot(val2, flag3 ? (-val) : val) < (flag3 ? 0.5f : 0.15f) || NavMesh.Raycast(((Component)this).transform.position, point2, ref val3, -1) || !DriverRoomTo(point2, flag3))
					{
						continue;
					}
					Vector3 val4 = point2 + val2 * (flag3 ? 3.4f : (-2.6f));
					Vector3 val5 = val4 - body.position;
					val5.y = 0f;
					if (!(((Vector3)(ref val5)).magnitude < 1.2f) && CartRoomAhead(((Vector3)(ref val5)).normalized, ((Vector3)(ref val5)).magnitude))
					{
						float num3 = push.Score * 12f + Flat(point, ((Component)companion).transform.position) * 0.7f + Mathf.Min(((Vector3)(ref val5)).magnitude, 5f) * 0.6f;
						num3 -= (1f - Vector3.Dot(val2, flag3 ? (-val) : val)) * 5f;
						if (!(num3 <= num))
						{
							num = num3;
							route = point2;
							cartRoute = val4;
							flag = true;
							flag2 = flag3;
						}
					}
				}
			}
			if (flag)
			{
				pulling = !flag2;
				driveDirection = route - ((Component)this).transform.position;
				driveDirection.y = 0f;
				((Vector3)(ref driveDirection)).Normalize();
			}
			if (flag && flag2)
			{
				HazardRoutes++;
				EnemyMod.Log.LogInfo((object)"Echo chose a cart route towards a measured drop/pit.");
			}
			if (flag)
			{
				EnemyMod.Log.LogInfo((object)$"Echo cart route: {((Component)this).transform.position} -> {route} (cart {((Component)cart).transform.position}).");
			}
			return flag;
		}

		private bool CartRoomAhead(Vector3 direction, float distance)
		{
			//IL_0038: 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_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: 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_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)cart) || !EchoCartApproach.BoundsOf(cart, out var bounds))
			{
				return false;
			}
			if (distance <= 0.01f || ((Vector3)(ref direction)).sqrMagnitude < 0.01f)
			{
				return true;
			}
			Vector3 val = ((Bounds)(ref bounds)).extents + new Vector3(0.05f, 0f, 0.05f);
			val.y = Mathf.Max(0.1f, val.y - 0.08f);
			return !Physics.BoxCastAll(((Bounds)(ref bounds)).center, val, ((Vector3)(ref direction)).normalized, Quaternion.identity, distance, EchoMotor.SolidMask, (QueryTriggerInteraction)1).Any((RaycastHit h) => !((Component)((RaycastHit)(ref h)).collider).transform.IsChildOf(((Component)cart).transform) && !((Component)((RaycastHit)(ref h)).collider).transform.IsChildOf(((Component)this).transform) && !IsCargo(((RaycastHit)(ref h)).collider));
		}

		private bool IsCargo(Collider collider)
		{
			PhysGrabObject componentInParent = ((Component)collider).GetComponentInParent<PhysGrabObject>();
			if (Object.op_Implicit((Object)(object)componentInParent) && Object.op_Implicit((Object)(object)cart))
			{
				return Cargo.Invoke(cart).Contains(componentInParent);
			}
			return false;
		}

		private bool DriverRoomTo(Vector3 destination, bool cartWillMoveAhead)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: 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_0047: 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_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = destination - ((Component)this).transform.position;
			val.y = 0f;
			return !Physics.CapsuleCastAll(((Component)this).transform.position + Vector3.up * 0.4f, ((Component)this).transform.position + Vector3.up * 1.45f, 0.32f, ((Vector3)(ref val)).normalized, ((Vector3)(ref val)).magnitude, EchoMotor.SolidMask, (QueryTriggerInteraction)1).Any((RaycastHit h) => !((Component)((RaycastHit)(ref h)).collider).transform.IsChildOf(((Component)this).transform) && (!cartWillMoveAhead || !((Component)((RaycastHit)(ref h)).collider).transform.IsChildOf(((Component)cart).transform)));
		}

		private PhysGrabber? PlayerHolder()
		{
			if (!Object.op_Implicit((Object)(object)item))
			{
				return null;
			}
			return ((IEnumerable<PhysGrabber>)item.playerGrabbing).FirstOrDefault((Func<PhysGrabber, bool>)((PhysGrabber p) => Object.op_Implicit((Object)(object)p) && Object.op_Implicit((Object)(object)p.playerAvatar) && !Disabled.Invoke(p.playerAvatar)));
		}

		private bool ValidCompanion()
		{
			if (Object.op_Implicit((Object)(object)companionAtGrab) && ((Component)companionAtGrab).gameObject.activeInHierarchy && !Disabled.Invoke(companionAtGrab))
			{
				return SemiFunc.PlayerGetList().Contains(companionAtGrab);
			}
			return false;
		}

		private bool Reachable(Vector3 wanted, out Vector3 point)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: 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_0050: Expected O, but got Unknown
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			wanted.y = ((Component)this).transform.position.y;
			point = wanted;
			NavMeshHit val = default(NavMeshHit);
			if (!((Behaviour)agent).enabled || !agent.isOnNavMesh || !NavMesh.SamplePosition(wanted, ref val, 1.2f, -1))
			{
				return false;
			}
			NavMeshPath val2 = new NavMeshPath();
			if (!agent.CalculatePath(((NavMeshHit)(ref val)).position, val2) || (int)val2.status != 0)
			{
				return false;
			}
			point = ((NavMeshHit)(ref val)).position;
			return true;
		}

		private bool GripClear()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: 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_0030: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = ((Component)this).transform.position + Vector3.up * 1.2f;
			Vector3 val2 = GrabPoint - val;
			return !Physics.RaycastAll(val, ((Vector3)(ref val2)).normalized, ((Vector3)(ref val2)).magnitude, EchoMotor.SolidMask, (QueryTriggerInteraction)1).Any((RaycastHit h) => !((Component)((RaycastHit)(ref h)).collider).transform.IsChildOf(((Component)this).transform) && (!Object.op_Implicit((Object)(object)cart) || !((Component)((RaycastHit)(ref h)).collider).transform.IsChildOf(((Component)cart).transform)) && !Object.op_Implicit((Object)(object)((Component)((RaycastHit)(ref h)).collider).GetComponentInParent<PlayerAvatar>()) && !Object.op_Implicit((Object)(object)((Component)((RaycastHit)(ref h)).collider).GetComponentInParent<PlayerController>()) && !Object.op_Implicit((Object)(object)((Component)((RaycastHit)(ref h)).collider).GetComponentInParent<PlayerHealthGrab>()) && !Object.op_Implicit((Object)(object)((Component)((RaycastHit)(ref h)).collider).GetComponentInParent<PlayerTumble>()));
		}

		private void FixedUpdate()
		{
			ValidateGripForPhysics();
		}

		internal static void AfterStockCartPhysics(PhysGrabCart source)
		{
			if (Claims.TryGetValue(source, out EchoCartTheft value) && Object.op_Implicit((Object)(object)value) && ((Behaviour)value).isActiveAndEnabled && value.ValidateGripForPhysics())
			{
				value.DriveCartPhysics();
			}
		}

		private bool ValidateGripForPhysics()
		{
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Invalid comparison between Unknown and I4
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: 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)
			if (!SemiFunc.IsMasterClientOrSingleplayer())
			{
				if (Object.op_Implicit((Object)(object)cart))
				{
					Release("authority changed");
				}
				return false;
			}
			if (!Object.op_Implicit((Object)(object)cart))
			{
				if (Stage != CartMischiefCycle.Stage.Idle)
				{
					Release("cart destroyed");
				}
				return false;
			}
			if (motor.IsTumbling || motor.IsCarried || Dead.Invoke(health) || enemy.IsStunned() || enemy.FreezeTimer > 0f || (int)enemy.CurrentState == 11 || !Usable(cart) || !Object.op_Implicit((Object)(object)item) || !Object.op_Implicit((Object)(object)body) || (companionAtGrab != null && !ValidCompanion()))
			{
				Release();
				return false;
			}
			PhysGrabber val = PlayerHolder();
			if (Object.op_Implicit((Object)(object)val))
			{
				bool num = Stage == CartMischiefCycle.Stage.Stealing;
				PlayerAvatar playerAvatar = val.playerAvatar;
				Release("real player reclaimed cart");
				if (num)
				{
					retaliation = playerAvatar;
				}
				return false;
			}
			if (!IsHolding)
			{
				return false;
			}
			if (Vector3.Distance(((Component)this).transform.position + Vector3.up, GrabPoint) > 4.2f || !GripClear())
			{
				Release("grip lost");
				return false;
			}
			return true;
		}

		private void DriveCartPhysics()
		{
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00fc: 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_0106: 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_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: 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_00b7: 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_0129: 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_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_021e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0215: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_0243: Unknown result type (might be due to invalid IL or missing references)
			//IL_0251: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_0276: Unknown result type (might be due to invalid IL or missing references)
			//IL_027c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0282: Unknown result type (might be due to invalid IL or missing references)
			//IL_0288: Unknown result type (might be due to invalid IL or missing references)
			//IL_028e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0295: 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_0306: 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_0329: Unknown result type (might be due to invalid IL or missing references)
			//IL_0333: Unknown result type (might be due to invalid IL or missing references)
			//IL_0335: Unknown result type (might be due to invalid IL or missing references)
			//IL_033a: Unknown result type (might be due to invalid IL or missing references)
			//IL_033e: 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_0363: Unknown result type (might be due to invalid IL or missing references)
			//IL_0376: Unknown result type (might be due to invalid IL or missing references)
			//IL_0396: Unknown result type (might be due to invalid IL or missing references)
			ApplyHeldPhysics();
			bool flag = Stage == CartMischiefCycle.Stage.Stealing;
			gripDistance = Mathf.MoveTowards(gripDistance, (flag && !pulling) ? 3.4f : 2.6f, Time.fixedDeltaTime * 2f);
			if (!flag && Flat(Destination, ((Component)this).transform.position) > 1f && Stage != CartMischiefCycle.Stage.Readying)
			{
				Vector3 val = Destination - ((Component)this).transform.position;
				val.y = 0f;
				Vector3 val2 = Vector3.RotateTowards(driveDirection, ((Vector3)(ref val)).normalized, Time.fixedDeltaTime * 2f, 0f);
				driveDirection = ((Vector3)(ref val2)).normalized;
			}
			Vector3 val3 = ((Component)this).transform.position + driveDirection * ((flag && pulling) ? (0f - gripDistance) : gripDistance) - body.position;
			val3.y = 0f;
			float num = (flag ? 4.5f : 2f);
			Vector3 val4 = motor.Velocity;
			val4.y = 0f;
			if (flag && !pulling && Flat(((Component)this).transform.position, route) > 0.6f)
			{
				val4 = driveDirection * CartTheftMotion.LeaderPace(Flat(body.position, ((Component)this).transform.position));
			}
			if (Stage == CartMischiefCycle.Stage.Readying || (flag && Flat(((Component)this).transform.position, route) < 0.6f))
			{
				val4 = Vector3.zero;
			}
			Vector3 val5 = Vector3.ClampMagnitude(val3 * 3f + val4, num);
			Vector3 velocity = body.velocity;
			velocity.y = 0f;
			float distance = ((Vector3)(ref velocity)).sqrMagnitude / 16f + 0.2f;
			Vector3 direction = ((((Vector3)(ref velocity)).sqrMagnitude > 0.25f) ? ((Vector3)(ref velocity)).normalized : ((Vector3)(ref val5)).normalized);
			physicallyBlocked = (((Vector3)(ref val5)).sqrMagnitude > 0.01f || ((Vector3)(ref velocity)).sqrMagnitude > 0.01f) && (!CartRoomAhead(direction, distance) || !CartRoomAhead(((Vector3)(ref val5)).normalized, 0.2f));
			(float, float) tuple = (physicallyBlocked ? CartTheftMotion.Acceleration(0f, 0f, 0f, 0f, velocity.x, velocity.z, 0f) : CartTheftMotion.Acceleration(val3.x, val3.z, val4.x, val4.z, velocity.x, velocity.z, num));
			Vector3 val6 = default(Vector3);
			((Vector3)(ref val6))..ctor(tuple.Item1, 0f, tuple.Item2);
			body.AddForce(val6, (ForceMode)5);
			Vector3 val7 = ((flag && pulling) ? (-driveDirection) : driveDirection);
			Quaternion val8 = body.rotation;
			float y = ((Quaternion)(ref val8)).eulerAngles.y;
			val8 = Quaternion.LookRotation(val7);
			float num2 = Mathf.DeltaAngle(y, ((Quaternion)(ref val8)).eulerAngles.y) * (MathF.PI / 180f);
			if (!physicallyBlocked)
			{
				body.AddTorque(Vector3.up * Mathf.Clamp(num2 * 7f - body.angularVelocity.y * 3f, -5f, 5f), (ForceMode)5);
			}
			item.EnemyInteractTimeSet();
			body.WakeUp();
			Pulled.Invoke(cart) = true;
		}

		private void ApplyHeldPhysics()
		{
			PhysGrabObject val = item;
			Rigidbody? obj = body;
			if (CartTheftMotion.CanRefreshOverride(MassTimer.Invoke(val), MassValue.Invoke(val), 4f))
			{
				val.OverrideMass(4f, 0.1f);
			}
			if (CartTheftMotion.CanRefreshOverride(DragTimer.Invoke(val), DragValue.Invoke(val), 0.5f))
			{
				val.OverrideDrag(0.5f, 0.1f);
			}
			if (CartTheftMotion.CanRefreshOverride(AngularDragTimer.Invoke(val), AngularDragValue.Invoke(val), 0.5f))
			{
				val.OverrideAngularDrag(0.5f, 0.1f);
			}
			obj.mass = MassValue.Invoke(val);
			obj.drag = DragValue.Invoke(val);
			obj.angularDrag = AngularDragValue.Invoke(val);
		}

		public void Release(string reason = "interrupted or finished")
		{
			if (IsHolding)
			{
				EnemyMod.Log.LogInfo((object)("Echo released cart: " + reason + "."));
			}
			if (cart != null && Claims.TryGetValue(cart, out EchoCartTheft value) && (Object)(object)value == (Object)(object)this)
			{
				Claims.Remove(cart);
				if (SemiFunc.IsMasterClientOrSingleplayer() && Object.op_Implicit((Object)(object)cart) && !Object.op_Implicit((Object)(object)PlayerHolder()))
				{
					ActiveCart.Invoke(cart) = false;
					Pulled.Invoke(cart) = false;
				}
			}
			if (cycle.Current != CartMischiefCycle.Stage.Idle)
			{
				nextTry = Time.time + Random.Range(40f, 65f);
			}
			cart = null;
			item = null;
			body = null;
			approachPath = null;
			companionAtGrab = null;
			cycle.Cancel();
			forced = (pulling = (physicallyBlocked = false));
		}

		private static float Flat(Vector3 a, Vector3 b)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			a.y = (b.y = 0f);
			return Vector3.Distance(a, b);
		}

		private void OnDisable()
		{
			SceneManager.activeSceneChanged -= SceneChanged;
			Release();
			retaliation = null;
		}
	}
	[HarmonyPatch(typeof(PhysGrabCart), "FixedUpdate")]
	internal static class EchoCartPhysics
	{
		[HarmonyPriority(0)]
		private static void Postfix(PhysGrabCart __instance)
		{
			EchoCartTheft.AfterStockCartPhysics(__instance);
		}
	}
	[HarmonyPatch(typeof(PhysGrabCart), "AutoTurnOff")]
	internal static class EchoCartMode
	{
		private static readonly FieldRef<PhysGrabCart, bool> Active = AccessTools.FieldRefAccess<PhysGrabCart, bool>("cartActive");

		private static bool Prefix(PhysGrabCart __instance)
		{
			if (!EchoCartTheft.Holding(__instance))
			{
				return true;
			}
			Active.Invoke(__instance) = true;
			return false;
		}
	}
	public sealed class EchoController : MonoBehaviour, IPunObservable
	{
		private float opportunityAt;

		private float opportunityScanAt;

		private float ambushUntil;

		private float lineUpScanAt;

		private float sprintStartedAt;

		private bool preparedOpportunity;

		private Vector3 runUpVictimPosition;

		private static readonly FieldRef<PlayerAvatar, bool> VictimTumbling = AccessTools.FieldRefAccess<PlayerAvatar, bool>("isTumbling");

		private static readonly FieldRef<PlayerAvatar, bool> Disabled = AccessTools.FieldRefAccess<PlayerAvatar, bool>("isDisabled");

		private static readonly FieldRef<EnemyHealth, bool> Dead = AccessTools.FieldRefAccess<EnemyHealth, bool>("dead");

		private static readonly FieldRef<Enemy, bool> Master = AccessTools.FieldRefAccess<Enemy, bool>("MasterClient");

		private static readonly FieldRef<PlayerAvatar, PlayerTumble> Tumble = AccessTools.FieldRefAccess<PlayerAvatar, PlayerTumble>("tumble");

		private Enemy enemy;

		private EnemyParent parent;

		private EnemyHealth health;

		private NavMeshAgent agent;

		private EchoMotor motor;

		private PhotonView view;

		private EchoAppearance appearance;

		private AudioSource voiceSource;

		private EchoHealthGrab healthGrab;

		private EchoCartTheft cartTheft;

		private EchoMonsterTactics monsterTactics;

		private bool dangerousRunUp;

		private Vector3 plannedVictim;

		private int remoteCartId = -1;

		private Vector3 remoteGripPoint;

		private PlayerAvatar? target;

		private HeadbuttCycle cycle;

		private readonly EchoBehaviourPolicy casual = new EchoBehaviourPolicy();

		private readonly EchoOriginalEncounterPolicy originalEncounter = new EchoOriginalEncounterPolicy();

		private float encounterCheckAt;

		private float encounterSampleAt;

		private float avoidOriginalUntil;

		private LevelPoint? lastInspectionPoint;

		private RoomVolume? lastInspectionRoom;

		private bool hasFleePoint;

		private bool hasFailedEscapePoint;

		private Vector3 escapeProgressPosition;

		private Vector3 failedEscapePoint;

		private float escapeRetryAt;

		private float escapeProgressAt;

		private int disguiseId = -1;

		private int builtId = -1;

		private int appearanceSeed;

		private float chooseAt;

		private float navigateAt;

		private float appearanceAt;

		private float casualAt;

		private float remoteSpeed;

		private float remotePhase;

		private float side;

		private HeadbuttCycle.Stage remoteStage;

		private Quaternion remoteRotation;

		private Vector3 casualPoint;

		private Vector3 lineUpPoint;

		private Vector3 chargePoint;

		private Vector3 fleePoint;

		private Vector3 manualPosition;

		private Vector3 lookPoint;

		private Vector3 previousTargetPosition;

		private Vector3 targetVelocity;

		private Vector3 remoteVelocity;

		private float lookAt;

		private float forceAttackUntil;

		private float movementSampleAt;

		private bool remoteTumble;

		private bool remoteCrouch;

		private float gestureAt;

		private float crouchUntil;

		private int expression;

		private static readonly FieldRef<PlayerAvatar, bool> PlayerCrouching = AccessTools.FieldRefAccess<PlayerAvatar, bool>("isCrouching");

		private static readonly FieldRef<EnemyHealth, int> CurrentHP = AccessTools.FieldRefAccess<EnemyHealth, int>("healthCurrent");

		private bool spawnPending;

		private bool manualSpawn;

		private bool hasCasualPoint;

		internal int PreviousDisguise = -1;

		public int OpportunisticSetups { get; private set; }

		public int CommittedHeadbutts { get; private set; }

		public int HazardRunUps { get; private set; }

		public bool CartGripping
		{
			get
			{
				if (!Authority)
				{
					return remoteCartId >= 0;
				}
				return cartTheft.IsHolding;
			}
		}

		public Vector3 CartGripPoint
		{
			get
			{
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0054: Unknown result type (might be due to invalid IL or missing references)
				//IL_0060: Unknown result type (might be due to invalid IL or missing references)
				if (Authority)
				{
					return cartTheft.GrabPoint;
				}
				PhotonView val = ((remoteCartId > 0) ? PhotonView.Find(remoteCartId) : null);
				PhysGrabCart val2 = (Object.op_Implicit((Object)(object)val) ? ((Component)val).GetComponent<PhysGrabCart>() : null);
				if (!Object.op_Implicit((Object)(object)val2) || !Object.op_Implicit((Object)(object)val2.cartGrabPoint))
				{
					return remoteGripPoint;
				}
				return val2.cartGrabPoint.position;
			}
		}

		public bool IsCrouching
		{
			get
			{
				if (!Authority)
				{
					return remoteCrouch;
				}
				return motor.Crouching;
			}
		}

		public int Expression => expression;

		private bool Authority => SemiFunc.IsMasterClientOrSingleplayer();

		public He