Decompiled source of PetPatch v1.3.1

PetPatch.dll

Decompiled 2 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("PetPatch")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+80f1b7e59c7886d9cf5dd24c97321d0625f3fa98")]
[assembly: AssemblyProduct("PetPatch")]
[assembly: AssemblyTitle("PetPatch")]
[assembly: AssemblyVersion("1.0.0.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 PetPatch
{
	[BepInPlugin("Mordel2Berde.PetPatch", "PetPatch", "1.3.1")]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGUID = "Mordel2Berde.PetPatch";

		public const string PluginName = "PetPatch";

		public const string PluginVersion = "1.3.1";

		internal static ManualLogSource Logger;

		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<float> BodyMargin;

		internal static ConfigEntry<float> ClearanceFactor;

		internal static ConfigEntry<float> PushSpeed;

		internal static ConfigEntry<bool> KeepTurningRoom;

		internal static ConfigEntry<float> IdleMinSeconds;

		internal static ConfigEntry<float> IdleMaxSeconds;

		internal static ConfigEntry<bool> StopForPlayers;

		internal static ConfigEntry<bool> StopForPets;

		internal static ConfigEntry<bool> LogBodySizes;

		private readonly Harmony _harmony = new Harmony("Mordel2Berde.PetPatch");

		private void Awake()
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expected O, but got Unknown
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Expected O, but got Unknown
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Expected O, but got Unknown
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Expected O, but got Unknown
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Expected O, but got Unknown
			Logger = ((BaseUnityPlugin)this).Logger;
			Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Keep the body of tamed creatures out of buildings and obstacles.");
			BodyMargin = ((BaseUnityPlugin)this).Config.Bind<float>("General", "BodyMargin", 0.15f, new ConfigDescription("Clearance added around the skeleton, in meters. Increase it if a body part still clips.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			ClearanceFactor = ((BaseUnityPlugin)this).Config.Bind<float>("General", "ClearanceFactor", 1.1f, new ConfigDescription("Multiplies the distance kept between the center of the creature and obstacles, after BodyMargin. The width never exceeds the collision capsule, so that doorways stay passable.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 2f), Array.Empty<object>()));
			PushSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("General", "PushSpeed", 1.5f, new ConfigDescription("Speed at which a clipping creature is moved out of an obstacle, in m/s.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 5f), Array.Empty<object>()));
			KeepTurningRoom = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "KeepTurningRoom", true, "Tamed creatures only roam to places they can actually reach, with enough room to turn around without their body entering an obstacle. Walking along an obstacle is still allowed.");
			IdleMinSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("General", "IdleMinSeconds", 5f, new ConfigDescription("Minimum time a roaming tamed creature stays in place after arriving or being interrupted, in seconds.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 600f), Array.Empty<object>()));
			IdleMaxSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("General", "IdleMaxSeconds", 45f, new ConfigDescription("Maximum time a roaming tamed creature stays in place after arriving or being interrupted, in seconds.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 600f), Array.Empty<object>()));
			StopForPlayers = ((BaseUnityPlugin)this).Config.Bind<bool>("Traffic", "StopForPlayers", true, "Tamed creatures stop instead of pushing a player standing in their way.");
			StopForPets = ((BaseUnityPlugin)this).Config.Bind<bool>("Traffic", "StopForPets", true, "Tamed creatures stop instead of pushing another tamed creature standing in their way.");
			LogBodySizes = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "LogBodySizes", false, "Log the body size measured for each tamed creature.");
			BodyClearance.Initialize();
			_harmony.PatchAll();
		}

		private void OnDestroy()
		{
			_harmony.UnpatchSelf();
			BodyClearance.Shutdown();
		}
	}
	internal static class IdleWait
	{
		private static readonly FieldRef<BaseAI, bool> Reached = AccessTools.FieldRefAccess<BaseAI, bool>("m_reachedRandomMoveTarget");

		private static readonly FieldRef<BaseAI, float> Timer = AccessTools.FieldRefAccess<BaseAI, float>("m_randomMoveUpdateTimer");

		internal static void Start(BaseAI ai)
		{
			Reached.Invoke(ai) = true;
			Timer.Invoke(ai) = Random.Range(Plugin.IdleMinSeconds.Value, Plugin.IdleMaxSeconds.Value);
		}
	}
	[HarmonyPatch(typeof(BaseAI), "IsValidRandomMovePoint")]
	internal static class RandomDestinationPatch
	{
		private static readonly float[] DistanceScales = new float[8] { 1f, 1f, 0.75f, 0.75f, 0.5f, 0.5f, 0.25f, 0.25f };

		private static readonly Func<BaseAI, Vector3, bool> IsValidPoint = AccessTools.MethodDelegate<Func<BaseAI, Vector3, bool>>(AccessTools.Method(typeof(BaseAI), "IsValidRandomMovePoint", (Type[])null, (Type[])null), (object)null, true);

		private static readonly List<Vector3> Path = new List<Vector3>();

		private static bool _searching;

		private static void Postfix(BaseAI __instance, Vector3 point, ref bool __result, Character ___m_character, AgentType ___m_pathAgentType, ref Vector3 ___m_randomMoveTarget)
		{
			//IL_0024: 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_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			if (_searching || !__result || !___m_character.IsTamed() || !BodyClearance.IsDestinationCheckActive(___m_character))
			{
				return;
			}
			_searching = true;
			try
			{
				if (FindDestination(__instance, ___m_character, ___m_pathAgentType, point, out var destination))
				{
					___m_randomMoveTarget = destination;
					return;
				}
			}
			finally
			{
				_searching = false;
			}
			__result = false;
			__instance.StopMoving();
			IdleWait.Start(__instance);
		}

		private static bool FindDestination(BaseAI ai, Character character, AgentType agentType, Vector3 point, out Vector3 destination)
		{
			//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_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: 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_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: 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_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: 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_0084: 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_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: 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_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			Vector3 position = ((Component)character).transform.position;
			Vector3 val = point - position;
			val.y = 0f;
			for (int i = 0; i < DistanceScales.Length; i++)
			{
				Quaternion val2 = ((i == 0) ? Quaternion.identity : Quaternion.Euler(0f, Random.Range(0f, 360f), 0f));
				Vector3 val3 = position + val2 * val * DistanceScales[i];
				if ((i <= 0 || IsValidPoint(ai, val3)) && Pathfinding.instance.GetPath(position, val3, Path, agentType, true, false, false) && Path.Count != 0 && !BodyClearance.IsWayBlocked(character, FirstLeg(position)))
				{
					Vector3 val4 = Path[Path.Count - 1];
					if (BodyClearance.HasRoomAt(character, val4))
					{
						destination = val4;
						return true;
					}
				}
			}
			destination = point;
			return false;
		}

		private static Vector3 FirstLeg(Vector3 origin)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0035: 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_0052: 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)
			foreach (Vector3 item in Path)
			{
				Vector3 result = item - origin;
				result.y = 0f;
				if (((Vector3)(ref result)).sqrMagnitude > 0.09f)
				{
					return result;
				}
			}
			return Vector3.zero;
		}
	}
	[HarmonyPatch(typeof(BaseAI), "RandomMovement")]
	internal static class ArrivalWaitPatch
	{
		private static void Prefix(bool ___m_reachedRandomMoveTarget, out bool __state)
		{
			__state = ___m_reachedRandomMoveTarget;
		}

		private static void Postfix(BaseAI __instance, Vector3 centerPoint, bool __state, bool ___m_reachedRandomMoveTarget, Character ___m_character)
		{
			//IL_0024: 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)
			if (!__state && ___m_reachedRandomMoveTarget && Plugin.Enabled.Value && ___m_character.IsTamed() && !__instance.IsAlerted() && !(Utils.DistanceXZ(centerPoint, ((Component)___m_character).transform.position) > __instance.m_randomMoveRange * 2f))
			{
				IdleWait.Start(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(BaseAI), "Follow")]
	internal static class FollowStopPatch
	{
		private static void Postfix(BaseAI __instance, GameObject go, Character ___m_character)
		{
			//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_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: 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)
			if ((Object)(object)go == (Object)null || !___m_character.IsTamed() || ___m_character.HaveRider())
			{
				return;
			}
			Vector3 moveDir = ___m_character.GetMoveDir();
			if (!(((Vector3)(ref moveDir)).sqrMagnitude > 0.0001f) && BodyClearance.LacksTurningRoom(___m_character, out var minDistance))
			{
				Vector3 val = go.transform.position - ((Component)___m_character).transform.position;
				val.y = 0f;
				if (((Vector3)(ref val)).magnitude > minDistance)
				{
					__instance.MoveTowards(val, false);
				}
			}
		}
	}
	[HarmonyPatch(typeof(Character), "UpdateMotion")]
	internal static class BodyClearance
	{
		private sealed class State
		{
			public bool Protected;

			public float Radius;

			public float Front;

			public float Rear;

			public float HalfWidth;

			public float Bottom;

			public float Top;

			public float NextScan;

			public float PauseUntil;

			public Vector3 Remaining;

			public Vector3 ContactDir;

			public float BestDepth = float.MaxValue;

			public float StuckTime;

			public float NextTrafficScan;

			public bool Blocked;

			public float NextRoomCheck;

			public bool HasRoomHere = true;
		}

		private const float ScanInterval = 0.1f;

		private const float DeadZone = 0.03f;

		private const float MaxCorrection = 1f;

		private const float MaxVerticalNormal = 0.4f;

		private const float MaxBoneDistance = 10f;

		private const float GiveUpAfter = 1.5f;

		private const float PauseDuration = 6f;

		private const float ProgressStep = 0.02f;

		private const float LookAheadBase = 0.3f;

		private const float LookAheadPerSpeed = 0.15f;

		private const int TurnSamples = 12;

		private const float RoomCheckInterval = 0.25f;

		private static readonly ConditionalWeakTable<Character, State> States = new ConditionalWeakTable<Character, State>();

		private static readonly FieldRef<Character, CapsuleCollider> CapsuleOf = AccessTools.FieldRefAccess<Character, CapsuleCollider>("m_collider");

		private static readonly Collider[] Overlaps = (Collider[])(object)new Collider[32];

		private static int _obstacleMask;

		private static int _characterMask;

		private static GameObject? _probeObject;

		private static BoxCollider? _probe;

		private static readonly FieldRef<Character, Rigidbody> BodyOf = AccessTools.FieldRefAccess<Character, Rigidbody>("m_body");

		internal static void Initialize()
		{
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Expected O, but got Unknown
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			_obstacleMask = LayerMask.GetMask(new string[4] { "Default", "static_solid", "Default_small", "piece" });
			_characterMask = LayerMask.GetMask(new string[3] { "character", "character_net", "character_noenv" });
			_probeObject = new GameObject("PetPatch_Probe");
			((Object)_probeObject).hideFlags = (HideFlags)61;
			_probeObject.layer = LayerMask.NameToLayer("Ignore Raycast");
			_probeObject.transform.position = new Vector3(0f, -10000f, 0f);
			Object.DontDestroyOnLoad((Object)(object)_probeObject);
			_probe = _probeObject.AddComponent<BoxCollider>();
		}

		internal static void Shutdown()
		{
			if ((Object)(object)_probeObject != (Object)null)
			{
				Object.Destroy((Object)(object)_probeObject);
			}
		}

		private static State GetState(Character character)
		{
			return States.GetValue(character, (Character c) => Measure(c, CapsuleOf.Invoke(c)));
		}

		internal static bool IsDestinationCheckActive(Character character)
		{
			if (Plugin.Enabled.Value && Plugin.KeepTurningRoom.Value && !character.IsFlying())
			{
				return !character.IsSwimming();
			}
			return false;
		}

		internal static bool HasRoomAt(Character character, Vector3 position)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			State state = GetState(character);
			if (state.Protected)
			{
				return HasTurningRoom(state, position);
			}
			return true;
		}

		internal static bool LacksTurningRoom(Character character, out float minDistance)
		{
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			State state = GetState(character);
			minDistance = Mathf.Max(state.Front, state.Radius) + 1f;
			if (!Plugin.Enabled.Value || !Plugin.KeepTurningRoom.Value || !state.Protected || character.IsFlying())
			{
				return false;
			}
			float time = Time.time;
			if (time >= state.NextRoomCheck)
			{
				state.NextRoomCheck = time + 0.25f;
				state.HasRoomHere = HasTurningRoom(state, ((Component)character).transform.position);
			}
			return !state.HasRoomHere;
		}

		private static bool HasTurningRoom(State state, Vector3 position)
		{
			//IL_0047: 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_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: 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_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: 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_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			float num = (state.Front + state.Rear) * 0.5f;
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor(state.HalfWidth, (state.Top - state.Bottom) * 0.5f, (state.Front - state.Rear) * 0.5f);
			Vector3 val2 = position + Vector3.up * ((state.Bottom + state.Top) * 0.5f);
			for (int i = 0; i < 12; i++)
			{
				Quaternion val3 = Quaternion.Euler(0f, (float)i * 360f / 12f, 0f);
				if (Physics.CheckBox(val2 + val3 * Vector3.forward * num, val, val3, _obstacleMask, (QueryTriggerInteraction)1))
				{
					return false;
				}
			}
			return true;
		}

		private static void Prefix(Character __instance, float dt, ref Vector3 ___m_moveDir, Rigidbody ___m_body)
		{
			if (!Plugin.Enabled.Value || !__instance.IsTamed())
			{
				return;
			}
			State state = GetState(__instance);
			if (CanAdjust(__instance, ___m_body))
			{
				float time = Time.time;
				if (Plugin.StopForPlayers.Value || Plugin.StopForPets.Value)
				{
					AvoidCharacters(__instance, state, time, ref ___m_moveDir, ___m_body);
				}
				if (state.Protected && time >= state.PauseUntil)
				{
					KeepBodyClear(__instance, state, time, dt, ref ___m_moveDir, ___m_body);
				}
			}
		}

		private static void AvoidCharacters(Character character, State state, float time, ref Vector3 moveDir, Rigidbody body)
		{
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			if (character.InAttack())
			{
				state.Blocked = false;
				return;
			}
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor(moveDir.x, 0f, moveDir.z);
			if (time >= state.NextTrafficScan && ((Vector3)(ref val)).sqrMagnitude > 0.0001f)
			{
				state.NextTrafficScan = time + 0.1f;
				state.Blocked = IsPathBlocked(character, state, ((Vector3)(ref val)).normalized, body);
				BaseAI baseAI = character.GetBaseAI();
				if (state.Blocked && (Object)(object)baseAI != (Object)null && !baseAI.IsAlerted())
				{
					IdleWait.Start(baseAI);
				}
			}
			if (state.Blocked)
			{
				moveDir = Vector3.zero;
			}
		}

		internal static bool IsWayBlocked(Character character, Vector3 direction)
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.Enabled.Value || (!Plugin.StopForPlayers.Value && !Plugin.StopForPets.Value))
			{
				return false;
			}
			direction.y = 0f;
			Rigidbody val = BodyOf.Invoke(character);
			if (((Vector3)(ref direction)).sqrMagnitude < 0.0001f || (Object)(object)val == (Object)null)
			{
				return false;
			}
			return IsPathBlocked(character, GetState(character), ((Vector3)(ref direction)).normalized, val);
		}

		private static bool IsPathBlocked(Character character, State state, Vector3 direction, Rigidbody body)
		{
			//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_000d: 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_0056: 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_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: 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)
			//IL_00a6: 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_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			Vector3 position = ((Component)character).transform.position;
			Vector3 linearVelocity = body.linearVelocity;
			linearVelocity.y = 0f;
			float num = Mathf.Max(state.Front, state.Radius) + 0.3f + ((Vector3)(ref linearVelocity)).magnitude * 0.15f;
			float num2 = Mathf.Max(state.Top, 0.5f);
			Vector3 val = position + direction * (num * 0.5f) + Vector3.up * ((0.1f + num2) * 0.5f);
			Vector3 val2 = default(Vector3);
			((Vector3)(ref val2))..ctor(state.Radius, (num2 - 0.1f) * 0.5f, num * 0.5f);
			int num3 = Physics.OverlapBoxNonAlloc(val, val2, Overlaps, Quaternion.LookRotation(direction), _characterMask, (QueryTriggerInteraction)1);
			for (int i = 0; i < num3; i++)
			{
				Character componentInParent = ((Component)Overlaps[i]).GetComponentInParent<Character>();
				if (!((Object)(object)componentInParent == (Object)null) && !((Object)(object)componentInParent == (Object)(object)character) && ShouldStopFor(componentInParent) && Vector3.Dot(((Component)componentInParent).transform.position - position, direction) > 0f)
				{
					return true;
				}
			}
			return false;
		}

		private static bool ShouldStopFor(Character other)
		{
			if (other.IsDead())
			{
				return false;
			}
			if (other.IsPlayer())
			{
				if (Plugin.StopForPlayers.Value && !other.InGhostMode())
				{
					return !other.IsDebugFlying();
				}
				return false;
			}
			if (Plugin.StopForPets.Value)
			{
				return other.IsTamed();
			}
			return false;
		}

		private static void KeepBodyClear(Character character, State state, float time, float dt, ref Vector3 moveDir, Rigidbody body)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: 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_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_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: 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_00a6: 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_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			if (time >= state.NextScan)
			{
				state.NextScan = time + 0.1f;
				Scan(character, state);
				TrackProgress(state, time);
			}
			if (!(state.ContactDir == Vector3.zero))
			{
				float num = Vector3.Dot(moveDir, state.ContactDir);
				if (num < 0f)
				{
					moveDir -= state.ContactDir * num;
				}
				float magnitude = ((Vector3)(ref state.Remaining)).magnitude;
				if (magnitude > 0.03f)
				{
					Vector3 val = state.ContactDir * Mathf.Min(magnitude, Plugin.PushSpeed.Value * dt);
					body.position += val;
					state.Remaining -= val;
				}
			}
		}

		private static bool CanAdjust(Character character, Rigidbody body)
		{
			if (body.isKinematic || character.IsDead() || character.IsAttached() || character.HaveRider() || character.IsFlying())
			{
				return false;
			}
			BaseAI baseAI = character.GetBaseAI();
			if (!((Object)(object)baseAI == (Object)null))
			{
				return !baseAI.IsSleeping();
			}
			return true;
		}

		private static State Measure(Character character, CapsuleCollider capsule)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: 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_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: 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_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			State state = new State();
			Transform transform = ((Component)character).transform;
			Vector3 position = transform.position;
			bool flag = false;
			float num = 0f;
			float num2 = (state.Radius = capsule.radius * transform.lossyScale.x);
			SkinnedMeshRenderer[] componentsInChildren = ((Component)character).GetComponentsInChildren<SkinnedMeshRenderer>();
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Transform[] bones = componentsInChildren[i].bones;
				foreach (Transform val in bones)
				{
					if (!((Object)(object)val == (Object)null))
					{
						Vector3 val2 = val.position - position;
						if (!(((Vector3)(ref val2)).magnitude > 10f))
						{
							float num3 = Vector3.Dot(val2, transform.forward);
							state.Front = Mathf.Max(state.Front, num3);
							state.Rear = Mathf.Min(state.Rear, num3);
							state.Top = Mathf.Max(state.Top, Vector3.Dot(val2, transform.up));
							num = Mathf.Max(num, Mathf.Abs(Vector3.Dot(val2, transform.right)));
							flag = true;
						}
					}
				}
			}
			if (!flag)
			{
				return state;
			}
			float value = Plugin.BodyMargin.Value;
			float value2 = Plugin.ClearanceFactor.Value;
			state.Front = (state.Front + value) * value2;
			state.Rear = (state.Rear - value) * value2;
			state.Top += value;
			state.HalfWidth = Mathf.Min((num + value) * value2, num2);
			state.Bottom = Mathf.Max(0.35f, state.Top * 0.3f);
			state.Protected = state.Top > state.Bottom && (state.Front > num2 || 0f - state.Rear > num2);
			if (Plugin.LogBodySizes.Value)
			{
				Plugin.Logger.LogInfo((object)($"{((Object)character).name}: front {state.Front:0.00}, rear {state.Rear:0.00}, half width {state.HalfWidth:0.00}, " + $"height {state.Bottom:0.00}-{state.Top:0.00}, capsule radius {num2:0.00}, protected: {state.Protected}"));
			}
			return state;
		}

		private static void Scan(Character character, State state)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: 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_004b: 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_0053: 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)
			//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)
			//IL_0098: 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_00a2: 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_00d1: 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_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: 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_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: 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_015b: 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_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			state.Remaining = Vector3.zero;
			state.ContactDir = Vector3.zero;
			if ((Object)(object)_probe == (Object)null)
			{
				return;
			}
			Transform transform = ((Component)character).transform;
			Vector3 val = Vector3.ProjectOnPlane(transform.forward, Vector3.up);
			if (((Vector3)(ref val)).sqrMagnitude < 0.0001f)
			{
				return;
			}
			Quaternion val2 = Quaternion.LookRotation(val);
			Vector3 val3 = transform.position + val2 * Vector3.forward * ((state.Front + state.Rear) * 0.5f) + Vector3.up * ((state.Bottom + state.Top) * 0.5f);
			Vector3 val4 = default(Vector3);
			((Vector3)(ref val4))..ctor(state.HalfWidth * 2f, state.Top - state.Bottom, state.Front - state.Rear);
			int num = Physics.OverlapBoxNonAlloc(val3, val4 * 0.5f, Overlaps, val2, _obstacleMask, (QueryTriggerInteraction)1);
			if (num == 0)
			{
				return;
			}
			_probe.size = val4;
			Vector3 val5 = Vector3.zero;
			Vector3 val7 = default(Vector3);
			float num2 = default(float);
			for (int i = 0; i < num; i++)
			{
				Collider val6 = Overlaps[i];
				if (!((Component)val6).transform.IsChildOf(transform))
				{
					Transform transform2 = ((Component)val6).transform;
					if (Physics.ComputePenetration((Collider)(object)_probe, val3 + val5, val2, val6, transform2.position, transform2.rotation, ref val7, ref num2) && !(Mathf.Abs(val7.y) > 0.4f))
					{
						val7.y = 0f;
						val5 += val7 * num2;
					}
				}
			}
			if (!(val5 == Vector3.zero))
			{
				state.Remaining = Vector3.ClampMagnitude(val5, 1f);
				state.ContactDir = ((Vector3)(ref val5)).normalized;
			}
		}

		private static void TrackProgress(State state, float time)
		{
			//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)
			//IL_0086: 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)
			float magnitude = ((Vector3)(ref state.Remaining)).magnitude;
			if (magnitude <= 0.03f)
			{
				state.BestDepth = float.MaxValue;
				state.StuckTime = 0f;
				return;
			}
			if (magnitude < state.BestDepth - 0.02f)
			{
				state.BestDepth = magnitude;
				state.StuckTime = 0f;
				return;
			}
			state.StuckTime += 0.1f;
			if (!(state.StuckTime < 1.5f))
			{
				state.PauseUntil = time + 6f;
				state.Remaining = Vector3.zero;
				state.ContactDir = Vector3.zero;
				state.BestDepth = float.MaxValue;
				state.StuckTime = 0f;
			}
		}
	}
}