Decompiled source of NpcWalk v1.0.0

plugins/Melissa.NpcWalk.dll

Decompiled 12 hours ago
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using FishNet.Object;
using FishyUI;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using SpongeMods.ModMenu;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Melissa.NpcWalk")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("Melissa.NpcWalk")]
[assembly: AssemblyTitle("NpcWalk")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
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 BepInEx
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	[Embedded]
	internal sealed class BepInAutoPluginAttribute : Attribute
	{
		public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace BepInEx.Preloader.Core.Patching
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	[Embedded]
	internal sealed class PatcherAutoPluginAttribute : Attribute
	{
		public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace Microsoft.CodeAnalysis
{
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace NpcWalk
{
	internal sealed class NpcCarry : MonoBehaviour
	{
		private int _worth;

		private string _label = "Corpse";

		private bool _carried;

		private Player? _carrier;

		public static NpcCarry Attach(GameObject corpse, string label, int worth)
		{
			NpcCarry npcCarry = corpse.GetComponent<NpcCarry>();
			if ((Object)(object)npcCarry == (Object)null)
			{
				npcCarry = corpse.AddComponent<NpcCarry>();
			}
			npcCarry._worth = worth;
			npcCarry._label = label;
			npcCarry.SetupInteract();
			return npcCarry;
		}

		private void SetupInteract()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				GameObject val = new GameObject("CorpseInteract");
				val.SetActive(false);
				val.transform.SetParent(((Component)this).transform, false);
				val.transform.localPosition = Vector3.up * 1f;
				SphereCollider val2 = val.AddComponent<SphereCollider>();
				val2.radius = 1.1f;
				((Collider)val2).isTrigger = true;
				CorpseInteractable corpseInteractable = val.AddComponent<CorpseInteractable>();
				corpseInteractable.Carry = this;
				Type typeFromHandle = typeof(Interactable);
				typeFromHandle.GetField("_interactCol", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(corpseInteractable, val2);
				typeFromHandle.GetField("_textTarget", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(corpseInteractable, ((Component)this).transform);
				val.SetActive(true);
				((Interactable)corpseInteractable).ToggleIsInteractable(true);
				Interactable val3 = Interactable.Get((Collider)(object)val2);
				Plugin.Log.LogInfo((object)$"[NpcCarry] '{((Object)this).name}' pickup ready (${_worth}), registered={(Object)(object)val3 == (Object)(object)corpseInteractable}");
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("[NpcCarry] interact setup fail: " + ex.Message));
			}
		}

		public void ToggleCarry(Player player)
		{
			if (_carried)
			{
				Drop();
			}
			else
			{
				Pickup(player);
			}
		}

		private void Pickup(Player player)
		{
			//IL_0077: 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)
			try
			{
				Transform val = null;
				try
				{
					PlayerHands hands = player.Hands;
					val = ((hands != null) ? hands.HandBoneRight : null);
				}
				catch
				{
				}
				if ((Object)(object)val == (Object)null)
				{
					Plugin.Log.LogWarning((object)"[NpcCarry] no hand bone, cannot carry");
					return;
				}
				((Component)this).GetComponent<NpcRagdoll.RagdollFreezer>()?.FreezeNow();
				_carrier = player;
				_carried = true;
				((Component)this).transform.SetParent(val, false);
				((Component)this).transform.localPosition = new Vector3(0f, -1.05f, 0.25f);
				((Component)this).transform.localRotation = Quaternion.Euler(15f, 0f, 0f);
				CorpseInteractable componentInChildren = ((Component)this).GetComponentInChildren<CorpseInteractable>(true);
				if (componentInChildren != null)
				{
					((Interactable)componentInChildren).ToggleIsInteractable(false);
				}
				Plugin.Log.LogInfo((object)("[NpcCarry] '" + ((Object)this).name + "' picked up by '" + ((Object)player).name + "'"));
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("[NpcCarry] pickup fail: " + ex.Message));
			}
		}

		private void Drop()
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				_carried = false;
				_carrier = null;
				((Component)this).transform.SetParent((Transform)null, true);
				((Component)this).GetComponent<NpcRagdoll.RagdollFreezer>()?.WakeFor(3f);
				CorpseInteractable componentInChildren = ((Component)this).GetComponentInChildren<CorpseInteractable>(true);
				if (componentInChildren != null)
				{
					((Interactable)componentInChildren).ToggleIsInteractable(true);
				}
				Plugin.Log.LogInfo((object)$"[NpcCarry] '{((Object)this).name}' dropped at {((Component)this).transform.position}");
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("[NpcCarry] drop fail: " + ex.Message));
			}
		}

		internal string PriceText()
		{
			return $"{_label}\n${_worth}\n{SpriteManager.GetPickUpInput()}";
		}
	}
	internal sealed class CorpseInteractable : Interactable
	{
		internal NpcCarry? Carry;

		private string _hoverText = "";

		public override void Hover()
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			_hoverText = (((Object)(object)Carry != (Object)null) ? Carry.PriceText() : "Corpse");
			PlayerUI.SetLookAtText(_hoverText, ((Interactable)this).TextTarget, default(Vector3), false);
			((Interactable)this).Hover();
		}

		public override void UnHover()
		{
			PlayerUI.HideLookAtText(_hoverText);
			((Interactable)this).UnHover();
		}

		public override void Interact(Player player)
		{
			((Interactable)this).Interact(player);
			((Interactable)this).UnHover();
			Carry?.ToggleCarry(player);
		}
	}
	[HarmonyPatch(typeof(NPC), "GetEyeDir")]
	internal static class NpcEyePatch
	{
		private const float FovHalfAngle = 65f;

		private static FieldInfo? _eyePosF;

		private static FieldInfo? _defaultEyeRotF;

		private static float _nextDbg;

		private static bool Prefix(NPC __instance, ref Quaternion __result)
		{
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_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_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: 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_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_0074: 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)
			try
			{
				Type typeFromHandle = typeof(NPC);
				if ((object)_eyePosF == null)
				{
					_eyePosF = typeFromHandle.GetField("_eyePos", BindingFlags.Instance | BindingFlags.NonPublic);
				}
				if ((object)_defaultEyeRotF == null)
				{
					_defaultEyeRotF = typeFromHandle.GetField("_defaultEyeRot", BindingFlags.Instance | BindingFlags.NonPublic);
				}
				if (_eyePosF == null || _defaultEyeRotF == null)
				{
					return true;
				}
				Vector3 val = (Vector3)(_eyePosF.GetValue(__instance) ?? ((object)((Component)__instance).transform.position));
				Player val2 = null;
				try
				{
					val2 = PlayerManager.GetNearestAlivePlayer(val);
				}
				catch
				{
				}
				if ((Object)(object)val2 == (Object)null || (Object)(object)val2.CamObject == (Object)null)
				{
					return true;
				}
				Vector3 position = val2.CamObject.position;
				Vector3 val3 = position - val;
				float magnitude = ((Vector3)(ref val3)).magnitude;
				if (magnitude < 0.001f)
				{
					return true;
				}
				float num = 14f;
				try
				{
					FieldInfo field = typeFromHandle.GetField("_playerEyeContactMaxDist", BindingFlags.Instance | BindingFlags.NonPublic);
					if (field != null)
					{
						num = (float)(field.GetValue(__instance) ?? ((object)14f));
					}
				}
				catch
				{
				}
				bool flag = magnitude <= num;
				bool flag2 = true;
				if (Time.time >= _nextDbg)
				{
					_nextDbg = Time.time + 5f;
					Plugin.Log.LogInfo((object)$"[NpcEyes] '{((Object)__instance).name}' dist={magnitude:F1}/{num:F0} ang={Vector3.Angle(((Component)__instance).transform.forward, val3):F0} tracking={flag && flag2}");
				}
				if (!flag || !flag2)
				{
					__result = (Quaternion)(_defaultEyeRotF.GetValue(__instance) ?? ((object)Quaternion.identity));
					return false;
				}
			}
			catch
			{
			}
			return true;
		}
	}
	internal sealed class NpcHealth : MonoBehaviour
	{
		private NPC? _npc;

		private int _hp;

		private bool _dead;

		private float _lastDamageTime = -10f;

		public bool Dead => _dead;

		public int Hp => _hp;

		public bool WasRecentlyDamaged()
		{
			return Time.time - _lastDamageTime < 0.8f;
		}

		private void Awake()
		{
			_npc = ((Component)this).GetComponent<NPC>();
			_hp = Plugin.NpcHealth.Value;
		}

		public static bool IsServer()
		{
			try
			{
				return (Object)(object)Server.Instance != (Object)null && ((NetworkBehaviour)Server.Instance).IsServerInitialized;
			}
			catch
			{
				return false;
			}
		}

		public void TakeDamage(int amount, Player? killer, bool ranged, Vector3 point)
		{
			if (!Plugin.CanKill.Value)
			{
				return;
			}
			Plugin.Log.LogInfo((object)$"[NpcHealth] TakeDamage enter '{((Object)this).name}' amt={amount} dead={_dead} server={IsServer()}");
			if (!_dead && amount > 0 && IsServer())
			{
				_hp -= Mathf.Abs(amount);
				_lastDamageTime = Time.time;
				Plugin.Log.LogInfo((object)string.Format("[NpcHealth] '{0}' took {1} {2} dmg from '{3}' hp={4}", ((Object)this).name, amount, ranged ? "ranged" : "melee", ((killer != null) ? ((Object)killer).name : null) ?? "?", _hp));
				if (_hp <= 0)
				{
					Die(killer, ranged);
				}
			}
		}

		private void Die(Player? killer, bool ranged)
		{
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			_dead = true;
			NpcWalker component = ((Component)this).GetComponent<NpcWalker>();
			if ((Object)(object)component != (Object)null)
			{
				component.Die();
			}
			Interactable[] componentsInChildren = ((Component)this).GetComponentsInChildren<Interactable>(true);
			foreach (Interactable val in componentsInChildren)
			{
				try
				{
					if ((Object)(object)val != (Object)null)
					{
						val.ToggleIsInteractable(false);
						((Behaviour)val).enabled = false;
					}
				}
				catch
				{
				}
			}
			NpcRagdoll.Build(((Component)this).gameObject);
			float num = (ranged ? Plugin.RangedMult.Value : Plugin.MeleeMult.Value);
			int num2 = Mathf.Max(1, Mathf.RoundToInt((float)Plugin.BaseBounty.Value * num));
			string text = (ranged ? "Ranged" : "Melee");
			NpcCarry.Attach(((Component)this).gameObject, ((Object)(object)_npc != (Object)null) ? ((Object)_npc).name : ((Object)this).name, num2);
			try
			{
				Player val2 = killer ?? Player.LocalPlayer;
				if ((Object)(object)val2 != (Object)null)
				{
					MoneyManager.AddMoney(num2, val2);
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("[NpcHealth] bounty pay fail: " + ex.Message));
			}
			try
			{
				Player val3 = killer ?? Player.LocalPlayer;
				if (val3 != null)
				{
					PlayerKillScore killScore = val3.KillScore;
					if (killScore != null)
					{
						killScore.AddKillScore(((Object)(object)_npc != (Object)null) ? ((Object)_npc).name : ((Object)this).name, num2, new List<Bonus>
						{
							new Bonus(text, num)
						});
					}
				}
			}
			catch (Exception ex2)
			{
				Plugin.Log.LogWarning((object)("[NpcHealth] killscore fail: " + ex2.Message));
			}
			Plugin.Log.LogInfo((object)$"[NpcHealth] '{((Object)this).name}' died ({text}) bounty=${num2}");
		}
	}
	[HarmonyPatch(typeof(DazedUtils), "PlayDeadPlayerHitEffects")]
	internal static class NpcHitHook
	{
		private static bool Prefix(Vector3 point, Vector3 dir, int damage, Player playerWhoHit)
		{
			//IL_002a: 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_009d: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!Plugin.CanKill.Value)
				{
					return true;
				}
				string arg = CallerName();
				Plugin.Log.LogInfo((object)$"[NpcHitHook] fx call by {arg} dmg={damage} at {point}");
				if (!NpcHealth.IsServer())
				{
					Plugin.Log.LogInfo((object)"[NpcHitHook] not server, skip");
					return true;
				}
				if (!IsNpcDamageCall())
				{
					return true;
				}
				bool ranged = IsRangedCall();
				NpcHealth npcHealth = NearestAliveNpc(point, 1.2f);
				if ((Object)(object)npcHealth == (Object)null)
				{
					Plugin.Log.LogInfo((object)"[NpcHitHook] no alive NPC near hit point");
					return true;
				}
				if (npcHealth.WasRecentlyDamaged())
				{
					return true;
				}
				npcHealth.TakeDamage(damage, playerWhoHit, ranged, point);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("[NpcHitHook] fail: " + ex.Message));
			}
			return true;
		}

		private static string CallerName()
		{
			try
			{
				StackTrace stackTrace = new StackTrace();
				for (int i = 1; i < 8 && i < stackTrace.FrameCount; i++)
				{
					MethodBase methodBase = stackTrace.GetFrame(i)?.GetMethod();
					if (!(methodBase == null) && !(methodBase.DeclaringType == null) && !(methodBase.DeclaringType == typeof(NpcHitHook)))
					{
						return methodBase.DeclaringType.Name + "::" + methodBase.Name;
					}
				}
			}
			catch
			{
			}
			return "?";
		}

		private static bool IsNpcDamageCall()
		{
			StackTrace stackTrace = new StackTrace();
			for (int i = 1; i < 8 && i < stackTrace.FrameCount; i++)
			{
				MethodBase methodBase = stackTrace.GetFrame(i)?.GetMethod();
				if (!(methodBase == null) && !(methodBase.DeclaringType == null))
				{
					switch (methodBase.DeclaringType.Name)
					{
					case "PlayerPunching":
					case "Melee":
					case "Weapon":
					case "ProjectileManager":
						return true;
					case "DeadPlayer":
						return false;
					}
				}
			}
			return false;
		}

		private static bool IsRangedCall()
		{
			StackTrace stackTrace = new StackTrace();
			for (int i = 1; i < 8 && i < stackTrace.FrameCount; i++)
			{
				MethodBase methodBase = stackTrace.GetFrame(i)?.GetMethod();
				if (!(methodBase == null) && !(methodBase.DeclaringType == null))
				{
					switch (methodBase.DeclaringType.Name)
					{
					case "Weapon":
					case "ProjectileManager":
						return true;
					case "PlayerPunching":
					case "Melee":
						return false;
					}
				}
			}
			return false;
		}

		private static NpcHealth? NearestAliveNpc(Vector3 point, float maxDist)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: 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_0054: Unknown result type (might be due to invalid IL or missing references)
			NpcHealth[] array = Object.FindObjectsByType<NpcHealth>((FindObjectsInactive)1, (FindObjectsSortMode)0);
			NpcHealth result = null;
			float num = maxDist * maxDist;
			NpcHealth[] array2 = array;
			foreach (NpcHealth npcHealth in array2)
			{
				if (!((Object)(object)npcHealth == (Object)null) && !npcHealth.Dead)
				{
					Vector3 val = ((Component)npcHealth).transform.position + Vector3.up * 1f - point;
					float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
					if (sqrMagnitude < num)
					{
						num = sqrMagnitude;
						result = npcHealth;
					}
				}
			}
			return result;
		}

		internal static NpcHealth? FromHit(Transform? t)
		{
			if ((Object)(object)t == (Object)null)
			{
				return null;
			}
			NPC val = ((Component)t).GetComponent<NPC>() ?? ((Component)t).GetComponentInParent<NPC>();
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			NpcHealth component = ((Component)val).GetComponent<NpcHealth>();
			if (!((Object)(object)component != (Object)null) || component.Dead)
			{
				return null;
			}
			return component;
		}
	}
	[HarmonyPatch(typeof(PlayerPunching), "HitTarget")]
	internal static class PunchHitPatch
	{
		private static void Postfix(PlayerPunching __instance, int side, Transform[] ____curTarget, Player ____player, int ____damage)
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!Plugin.CanKill.Value || !NpcHealth.IsServer() || ____curTarget == null || side < 0 || side >= ____curTarget.Length)
				{
					return;
				}
				NpcHealth npcHealth = NpcHitHook.FromHit(____curTarget[side]);
				if (!((Object)(object)npcHealth == (Object)null))
				{
					int amount;
					try
					{
						amount = (ServerSettings.OneShotEnabled ? 99999 : ____damage);
					}
					catch
					{
						amount = ____damage;
					}
					npcHealth.TakeDamage(amount, ____player, ranged: false, ((Component)npcHealth).transform.position);
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("[PunchHitPatch] fail: " + ex.Message));
			}
		}
	}
	[HarmonyPatch(typeof(ProjectileManager), "Hit")]
	internal static class ProjectileHitPatch
	{
		private static void Postfix(Projectile projectile, RaycastHit hit)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (Plugin.CanKill.Value && NpcHealth.IsServer() && projectile != null)
				{
					NpcHealth npcHealth = NpcHitHook.FromHit(((RaycastHit)(ref hit)).transform);
					if (!((Object)(object)npcHealth == (Object)null))
					{
						npcHealth.TakeDamage(projectile.Damage, projectile.Owner, ranged: true, ((RaycastHit)(ref hit)).point);
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("[ProjectileHitPatch] fail: " + ex.Message));
			}
		}
	}
	internal static class NpcRagdoll
	{
		private readonly struct BoneSpec
		{
			public readonly string Name;

			public readonly float Mass;

			public readonly float Radius;

			public BoneSpec(string name, float mass, float radius)
			{
				Name = name;
				Mass = mass;
				Radius = radius;
			}
		}

		internal sealed class RagdollFreezer : MonoBehaviour
		{
			private readonly List<Rigidbody> _bodies = new List<Rigidbody>();

			private float _deadline = -1f;

			private float _quietSince = -1f;

			public void Arm(IEnumerable<Rigidbody> bodies)
			{
				_bodies.Clear();
				_bodies.AddRange(bodies);
				_deadline = Time.time + 12f;
				_quietSince = -1f;
			}

			public void FreezeNow()
			{
				//IL_0021: 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)
				foreach (Rigidbody body in _bodies)
				{
					if (!((Object)(object)body == (Object)null))
					{
						try
						{
							body.linearVelocity = Vector3.zero;
							body.angularVelocity = Vector3.zero;
							body.isKinematic = true;
						}
						catch
						{
						}
					}
				}
				_deadline = -1f;
				_quietSince = -1f;
			}

			public void WakeFor(float seconds)
			{
				foreach (Rigidbody body in _bodies)
				{
					if ((Object)(object)body != (Object)null)
					{
						try
						{
							body.isKinematic = false;
						}
						catch
						{
						}
					}
				}
				_deadline = Time.time + Mathf.Max(seconds, 3f) + 8f;
				_quietSince = -1f;
			}

			private void Update()
			{
				//IL_006b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0070: 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_0085: Unknown result type (might be due to invalid IL or missing references)
				if (_deadline < 0f)
				{
					return;
				}
				if (Time.time >= _deadline)
				{
					FreezeNow();
					Plugin.Log.LogInfo((object)("[NpcRagdoll] '" + ((Object)this).name + "' frozen by timeout"));
					return;
				}
				bool flag = true;
				foreach (Rigidbody body in _bodies)
				{
					if ((Object)(object)body == (Object)null || body.isKinematic)
					{
						continue;
					}
					Vector3 val = body.linearVelocity;
					if (!(((Vector3)(ref val)).sqrMagnitude > 0.16f))
					{
						val = body.angularVelocity;
						if (!(((Vector3)(ref val)).sqrMagnitude > 0.5f))
						{
							continue;
						}
					}
					flag = false;
					break;
				}
				if (!flag)
				{
					_quietSince = -1f;
					return;
				}
				if (_quietSince < 0f)
				{
					_quietSince = Time.time;
				}
				if (Time.time - _quietSince >= 1f)
				{
					FreezeNow();
					Plugin.Log.LogInfo((object)("[NpcRagdoll] '" + ((Object)this).name + "' settled, frozen"));
				}
			}
		}

		private static readonly BoneSpec[] Bones = new BoneSpec[10]
		{
			new BoneSpec("Body", 22f, 0.3f),
			new BoneSpec("Head", 5f, 0.18f),
			new BoneSpec("ArmUpper_L", 4f, 0.11f),
			new BoneSpec("ArmUpper_R", 4f, 0.11f),
			new BoneSpec("ArmLower_L", 3f, 0.09f),
			new BoneSpec("ArmLower_R", 3f, 0.09f),
			new BoneSpec("LegUpper_L", 6f, 0.13f),
			new BoneSpec("LegUpper_R", 6f, 0.13f),
			new BoneSpec("LegLower_L", 4f, 0.1f),
			new BoneSpec("LegLower_R", 4f, 0.1f)
		};

		public static void Build(GameObject root)
		{
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: 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_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0241: Unknown result type (might be due to invalid IL or missing references)
			//IL_024a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			//IL_025c: Unknown result type (might be due to invalid IL or missing references)
			Collider[] componentsInChildren = root.GetComponentsInChildren<Collider>(true);
			foreach (Collider val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null) && !val.isTrigger)
				{
					val.isTrigger = true;
				}
			}
			Dictionary<Transform, Rigidbody> dictionary = new Dictionary<Transform, Rigidbody>();
			int num = 0;
			BoneSpec[] bones = Bones;
			for (int j = 0; j < bones.Length; j++)
			{
				BoneSpec boneSpec = bones[j];
				Transform val2 = null;
				Transform[] componentsInChildren2 = root.GetComponentsInChildren<Transform>(true);
				foreach (Transform val3 in componentsInChildren2)
				{
					if ((Object)(object)val3 != (Object)null && ((Object)val3).name == boneSpec.Name)
					{
						val2 = val3;
						break;
					}
				}
				if ((Object)(object)val2 == (Object)null || (Object)(object)((Component)val2).GetComponent<Rigidbody>() != (Object)null)
				{
					continue;
				}
				try
				{
					SphereCollider val4 = ((Component)val2).gameObject.AddComponent<SphereCollider>();
					val4.radius = boneSpec.Radius;
					((Collider)val4).isTrigger = false;
					Rigidbody val5 = ((Component)val2).gameObject.AddComponent<Rigidbody>();
					val5.mass = boneSpec.Mass;
					val5.linearDamping = 1.5f;
					val5.angularDamping = 5f;
					val5.collisionDetectionMode = (CollisionDetectionMode)0;
					val5.interpolation = (RigidbodyInterpolation)1;
					val5.sleepThreshold = 0.3f;
					dictionary[val2] = val5;
					Rigidbody value = null;
					Transform parent = val2.parent;
					while ((Object)(object)parent != (Object)null && !dictionary.TryGetValue(parent, out value))
					{
						parent = parent.parent;
					}
					if ((Object)(object)parent != (Object)null && (Object)(object)value != (Object)null)
					{
						CharacterJoint val6 = ((Component)val2).gameObject.AddComponent<CharacterJoint>();
						((Joint)val6).connectedBody = value;
						val6.enableProjection = false;
						bool flag = boneSpec.Name.StartsWith("Leg");
						SoftJointLimit lowTwistLimit = val6.lowTwistLimit;
						SoftJointLimit highTwistLimit = val6.highTwistLimit;
						SoftJointLimit swing1Limit = val6.swing1Limit;
						SoftJointLimit swing2Limit = val6.swing2Limit;
						((SoftJointLimit)(ref lowTwistLimit)).limit = (flag ? (-25f) : (-60f));
						((SoftJointLimit)(ref highTwistLimit)).limit = (flag ? 25f : 60f);
						((SoftJointLimit)(ref swing1Limit)).limit = (flag ? 30f : 80f);
						((SoftJointLimit)(ref swing2Limit)).limit = (flag ? 30f : 80f);
						val6.lowTwistLimit = lowTwistLimit;
						val6.highTwistLimit = highTwistLimit;
						val6.swing1Limit = swing1Limit;
						val6.swing2Limit = swing2Limit;
					}
					num++;
				}
				catch (Exception ex)
				{
					Plugin.Log.LogWarning((object)("[NpcRagdoll] bone '" + boneSpec.Name + "' fail: " + ex.Message));
				}
			}
			Plugin.Log.LogInfo((object)$"[NpcRagdoll] '{((Object)root).name}' ragdolled ({num} bodies)");
			RagdollFreezer ragdollFreezer = root.GetComponent<RagdollFreezer>();
			if ((Object)(object)ragdollFreezer == (Object)null)
			{
				ragdollFreezer = root.AddComponent<RagdollFreezer>();
			}
			ragdollFreezer.Arm(dictionary.Values);
		}
	}
	internal static class NpcSpongeMenu
	{
		[MethodImpl(MethodImplOptions.NoInlining)]
		public static void Ensure()
		{
			SpongeMenu.Tab("Melissa.NpcWalk", "NPC Walk", 60).Heading("Walking").Toggle("Enabled (off = walk home, stand)", Plugin.Enabled)
				.Toggle("Sitting NPCs wander", Plugin.SittingWalk)
				.Note("Speed in m/s. Radius = roam step, leash at 2x.")
				.Number("Walk speed", Plugin.WalkSpeed, 0f, 5f)
				.Number("Wander radius", Plugin.WanderRadius, 1f, 8f)
				.Number("Look distance", Plugin.LookDistance, 0f, 15f)
				.Heading("Fun")
				.Toggle("Party mode (hop + spin)", Plugin.PartyMode);
		}
	}
	internal static class NpcSpongeBridge
	{
		[MethodImpl(MethodImplOptions.NoInlining)]
		public static void Ensure()
		{
			try
			{
				NpcSpongeMenu.Ensure();
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("SpongeMenu init fail: " + ex.Message));
			}
		}
	}
	internal static class NpcUi
	{
		private static Window? _window;

		[MethodImpl(MethodImplOptions.NoInlining)]
		public static void Ensure()
		{
			if (_window != null)
			{
				return;
			}
			_window = Window.Create("npcwalk", "NPC Walk", 420f, 480f);
			if (_window != null)
			{
				_window.OpenInMenus = true;
				_window.Frosted = false;
				_window.Resizable = false;
				_window.Rows().Header("walking").Toggle("enabled", Plugin.Enabled)
					.Tip("off = everyone walks home and stands still.")
					.Toggle("sitting walk", Plugin.SittingWalk)
					.Tip("sitting NPCs get up and wander too.")
					.Slider("walk speed", Plugin.WalkSpeed, 0f, 5f)
					.Tip("m/s. 1.2 is a stroll, 4 is a jog.")
					.Slider("wander radius", Plugin.WanderRadius, 1f, 8f)
					.Slider("look distance", Plugin.LookDistance, 0f, 15f)
					.Space(0.4f)
					.Header("fun")
					.Toggle("party mode", Plugin.PartyMode)
					.Tip("hopping and spinning. pure fun.")
					.Space(0.4f)
					.Header("controls")
					.Keybind("menu key", Plugin.MenuKey)
					.Tip("opens this window.")
					.Readout("debug", (Func<string>)(() => NpcWalkController.Summary));
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		public static void Toggle()
		{
			Ensure();
			Window? window = _window;
			if (window != null)
			{
				window.Toggle();
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		public static void Refresh()
		{
			Window? window = _window;
			if (window != null)
			{
				window.Refresh();
			}
		}
	}
	internal static class NpcUiBridge
	{
		[MethodImpl(MethodImplOptions.NoInlining)]
		public static void Ensure()
		{
			try
			{
				NpcUi.Ensure();
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("FishyUI init fail: " + ex.Message));
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		public static void Toggle()
		{
			try
			{
				NpcUi.Toggle();
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("FishyUI toggle fail: " + ex.Message));
			}
		}
	}
	internal static class NpcWalkController
	{
		private static float _nextScan;

		private static bool _probed;

		private static bool _fullProbeDone;

		private const float ScanInterval = 5f;

		private static readonly Dictionary<NPC, (float dist, float sqr, float rot)> _origEyes = new Dictionary<NPC, (float, float, float)>();

		public static string Summary
		{
			get
			{
				try
				{
					NPC[] array = Object.FindObjectsByType<NPC>((FindObjectsInactive)1, (FindObjectsSortMode)0);
					NpcWalker[] array2 = Object.FindObjectsByType<NpcWalker>((FindObjectsInactive)1, (FindObjectsSortMode)0);
					int num = 0;
					int num2 = 0;
					NPC[] array3 = array;
					foreach (NPC val in array3)
					{
						if (!((Object)(object)val == (Object)null))
						{
							if ((Object)(object)((Component)val).GetComponent<NpcHealth>() != (Object)null && ((Component)val).GetComponent<NpcHealth>().Dead)
							{
								num2++;
							}
							else if (IsSitting(val))
							{
								num++;
							}
						}
					}
					return $"npc={array.Length} walking={array2.Length} sitting={num} dead={num2}";
				}
				catch
				{
					return "n/a";
				}
			}
		}

		public static void Init()
		{
			_nextScan = 0f;
			_probed = false;
			_fullProbeDone = false;
			Plugin.Log.LogInfo((object)"NpcWalkController init: scanning NPC...");
			Scan(now: true);
		}

		public static void Tick()
		{
			if (!Plugin.Enabled.Value)
			{
				RestoreEyes();
				if (Time.unscaledTime >= _nextScan)
				{
					Scan(now: false);
				}
				CollectRetired();
			}
			else
			{
				if (Time.unscaledTime >= _nextScan)
				{
					Scan(now: false);
				}
				CollectRetired();
			}
		}

		private static void CollectRetired()
		{
			NpcWalker[] array = Object.FindObjectsByType<NpcWalker>((FindObjectsInactive)1, (FindObjectsSortMode)0);
			NpcWalker[] array2 = array;
			foreach (NpcWalker npcWalker in array2)
			{
				if ((Object)(object)npcWalker != (Object)null && npcWalker.RetiredDone)
				{
					Object.Destroy((Object)(object)npcWalker);
				}
			}
		}

		public static void Dispose()
		{
			NpcWalker[] array = Object.FindObjectsByType<NpcWalker>((FindObjectsInactive)1, (FindObjectsSortMode)0);
			foreach (NpcWalker npcWalker in array)
			{
				if ((Object)(object)npcWalker != (Object)null)
				{
					Object.Destroy((Object)(object)npcWalker);
				}
			}
		}

		public static void RefreshWalkers()
		{
			NPC[] array = Object.FindObjectsByType<NPC>((FindObjectsInactive)1, (FindObjectsSortMode)0);
			if (!Plugin.Enabled.Value)
			{
				NPC[] array2 = array;
				foreach (NPC val in array2)
				{
					if (val != null)
					{
						((Component)val).GetComponent<NpcWalker>()?.TeleportHome();
					}
				}
				_nextScan = Time.unscaledTime + 5f;
				return;
			}
			NPC[] array3 = array;
			foreach (NPC val2 in array3)
			{
				if (!((Object)(object)val2 == (Object)null))
				{
					bool flag = !IsStationary(val2) && (!IsSitting(val2) || Plugin.SittingWalk.Value);
					NpcWalker component = ((Component)val2).GetComponent<NpcWalker>();
					if (flag && (Object)(object)component == (Object)null)
					{
						((Component)val2).gameObject.AddComponent<NpcWalker>();
						Plugin.Log.LogInfo((object)$"NpcWalker attached to NPC id={val2.ID} '{((Object)val2).name}' (refresh)");
					}
					else if (!flag && (Object)(object)component != (Object)null && !component.Retired)
					{
						component.GoHomeAndStop();
						Plugin.Log.LogInfo((object)$"NPC id={val2.ID} '{((Object)val2).name}' retiring home");
					}
				}
			}
			_nextScan = Time.unscaledTime + 5f;
		}

		private static void Scan(bool now)
		{
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			_nextScan = Time.unscaledTime + 5f;
			NPC[] array;
			try
			{
				array = Object.FindObjectsByType<NPC>((FindObjectsInactive)1, (FindObjectsSortMode)0);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Find NPC fail: " + ex.Message));
				return;
			}
			if (array.Length == 0)
			{
				if (now)
				{
					Plugin.Log.LogWarning((object)"No NPC found (menu scene? go to island). Will rescan.");
				}
				return;
			}
			Plugin.Log.LogInfo((object)$"NPC count: {array.Length}");
			NPC[] array2 = array;
			foreach (NPC val in array2)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				if (!_probed)
				{
					Probe(val);
				}
				if (Plugin.CanKill.Value && (Object)(object)((Component)val).GetComponent<NpcHealth>() == (Object)null)
				{
					((Component)val).gameObject.AddComponent<NpcHealth>();
					Plugin.Log.LogInfo((object)$"NpcHealth attached to NPC id={val.ID} '{((Object)val).name}'");
				}
				if (IsStationary(val) || (IsSitting(val) && !Plugin.SittingWalk.Value))
				{
					if ((Object)(object)((Component)val).GetComponent<NpcWalker>() == (Object)null)
					{
						Plugin.Log.LogInfo((object)$"NPC id={val.ID} '{((Object)val).name}' stays put (stationary/sitting)");
					}
				}
				else
				{
					NpcWalker component = ((Component)val).GetComponent<NpcWalker>();
					if ((Object)(object)component == (Object)null)
					{
						component = ((Component)val).gameObject.AddComponent<NpcWalker>();
						Plugin.Log.LogInfo((object)$"NpcWalker attached to NPC id={val.ID} '{((Object)val).name}' pos={((Component)val).transform.position}");
					}
				}
				ExtendEyeContact(val);
			}
			_probed = true;
		}

		internal static bool IsStationary(NPC npc)
		{
			try
			{
				string text = Plugin.StationaryNpcs.Value ?? "";
				string[] array = text.Split(',');
				foreach (string text2 in array)
				{
					string text3 = text2.Trim();
					if (text3.Length != 0)
					{
						if (text3.Equals(npc.ID.ToString(), StringComparison.OrdinalIgnoreCase))
						{
							return true;
						}
						if (((Object)npc).name.IndexOf(text3, StringComparison.OrdinalIgnoreCase) >= 0)
						{
							return true;
						}
					}
				}
			}
			catch
			{
			}
			return false;
		}

		internal static bool IsSitting(NPC npc)
		{
			//IL_007a: 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_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: 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_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_00ab: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Transform val = null;
				Transform val2 = null;
				Transform[] componentsInChildren = ((Component)npc).GetComponentsInChildren<Transform>(true);
				foreach (Transform val3 in componentsInChildren)
				{
					if (!((Object)(object)val3 == (Object)null))
					{
						if (((Object)val3).name == "LegUpper_L")
						{
							val = val3;
						}
						else if (((Object)val3).name == "LegLower_L")
						{
							val2 = val3;
						}
					}
				}
				if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
				{
					return false;
				}
				Vector3 val4 = val2.position - val.position;
				Vector3 val5 = new Vector3(val4.x, 0f, val4.z);
				float magnitude = ((Vector3)(ref val5)).magnitude;
				float num = Mathf.Abs(val4.y);
				bool flag = magnitude > num * 0.9f;
				if (flag)
				{
					Plugin.Log.LogInfo((object)$"NPC id={npc.ID} '{((Object)npc).name}' detected sitting (thigh h={magnitude:F2} v={num:F2})");
				}
				return flag;
			}
			catch
			{
			}
			return false;
		}

		private static void ExtendEyeContact(NPC npc)
		{
			try
			{
				Type typeFromHandle = typeof(NPC);
				FieldInfo field = typeFromHandle.GetField("_playerEyeContactMaxDist", BindingFlags.Instance | BindingFlags.NonPublic);
				FieldInfo field2 = typeFromHandle.GetField("_playerEyeContactMaxDistSqr", BindingFlags.Instance | BindingFlags.NonPublic);
				FieldInfo field3 = typeFromHandle.GetField("_maxEyeRot", BindingFlags.Instance | BindingFlags.NonPublic);
				if (!(field == null) && !(field2 == null) && !(field3 == null))
				{
					if (!_origEyes.ContainsKey(npc))
					{
						_origEyes[npc] = ((float)(field.GetValue(npc) ?? ((object)4f)), (float)(field2.GetValue(npc) ?? ((object)16f)), (float)(field3.GetValue(npc) ?? ((object)45f)));
					}
					field.SetValue(npc, 14f);
					field2.SetValue(npc, 196f);
					field3.SetValue(npc, 180f);
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("ExtendEyeContact fail on '" + ((Object)npc).name + "': " + ex.Message));
			}
		}

		private static void RestoreEyes()
		{
			if (_origEyes.Count == 0)
			{
				return;
			}
			try
			{
				Type typeFromHandle = typeof(NPC);
				FieldInfo field = typeFromHandle.GetField("_playerEyeContactMaxDist", BindingFlags.Instance | BindingFlags.NonPublic);
				FieldInfo field2 = typeFromHandle.GetField("_playerEyeContactMaxDistSqr", BindingFlags.Instance | BindingFlags.NonPublic);
				FieldInfo field3 = typeFromHandle.GetField("_maxEyeRot", BindingFlags.Instance | BindingFlags.NonPublic);
				if (field == null || field2 == null || field3 == null)
				{
					return;
				}
				foreach (KeyValuePair<NPC, (float, float, float)> origEye in _origEyes)
				{
					if (!((Object)(object)origEye.Key == (Object)null))
					{
						try
						{
							field.SetValue(origEye.Key, origEye.Value.Item1);
							field2.SetValue(origEye.Key, origEye.Value.Item2);
							field3.SetValue(origEye.Key, origEye.Value.Item3);
						}
						catch
						{
						}
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("RestoreEyes fail: " + ex.Message));
			}
			finally
			{
				_origEyes.Clear();
			}
		}

		private static void Probe(NPC npc)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: 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_025c: Expected O, but got Unknown
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0474: Unknown result type (might be due to invalid IL or missing references)
			//IL_0479: Unknown result type (might be due to invalid IL or missing references)
			//IL_0467: Unknown result type (might be due to invalid IL or missing references)
			//IL_046d: Unknown result type (might be due to invalid IL or missing references)
			GameObject gameObject = ((Component)npc).gameObject;
			List<string> obj = new List<string>
			{
				$"PROBE NPC id={npc.ID} name='{((Object)gameObject).name}'",
				$"  pos={gameObject.transform.position} rot={gameObject.transform.eulerAngles}"
			};
			Animator componentInChildren = gameObject.GetComponentInChildren<Animator>(true);
			obj.Add("  Animator=" + (((componentInChildren != null) ? ((Object)componentInChildren).name : null) ?? "none"));
			Animation componentInChildren2 = gameObject.GetComponentInChildren<Animation>(true);
			obj.Add("  Animation(legacy)=" + (((componentInChildren2 != null) ? ((Object)componentInChildren2).name : null) ?? "none"));
			Rigidbody componentInChildren3 = gameObject.GetComponentInChildren<Rigidbody>(true);
			obj.Add("  Rigidbody=" + (((componentInChildren3 != null) ? ((Object)componentInChildren3).name : null) ?? "none"));
			CharacterController componentInChildren4 = gameObject.GetComponentInChildren<CharacterController>(true);
			obj.Add("  CharacterController=" + (((componentInChildren4 != null) ? ((Object)componentInChildren4).name : null) ?? "none"));
			obj.Add("  Collider=" + (((object)gameObject.GetComponentInChildren<Collider>(true))?.GetType().Name ?? "none"));
			List<string> list = obj;
			Component component = gameObject.GetComponent("NavMeshAgent");
			list.Add("  NavMeshAgent=" + (((Object)(object)component != (Object)null) ? ((Object)component).name : "none"));
			Component component2 = gameObject.GetComponent("PlayerLegs");
			list.Add("  PlayerLegs=" + (((Object)(object)component2 != (Object)null) ? "FOUND" : "none"));
			Animator componentInChildren5 = gameObject.GetComponentInChildren<Animator>(true);
			if ((Object)(object)componentInChildren5 != (Object)null)
			{
				RuntimeAnimatorController runtimeAnimatorController = componentInChildren5.runtimeAnimatorController;
				list.Add("  AnimatorController=" + (((runtimeAnimatorController != null) ? ((Object)runtimeAnimatorController).name : null) ?? "none"));
				if (componentInChildren5.parameters != null)
				{
					AnimatorControllerParameter[] parameters = componentInChildren5.parameters;
					foreach (AnimatorControllerParameter val in parameters)
					{
						list.Add($"    param: {val.name} ({val.type})");
					}
				}
			}
			Animation componentInChildren6 = gameObject.GetComponentInChildren<Animation>(true);
			if ((Object)(object)componentInChildren6 != (Object)null)
			{
				foreach (AnimationState item in componentInChildren6)
				{
					AnimationState val2 = item;
					list.Add("    legacy clip: " + val2.name);
				}
			}
			Transform[] componentsInChildren = gameObject.GetComponentsInChildren<Transform>(true);
			list.Add($"  children={componentsInChildren.Length}");
			bool flag = !_fullProbeDone;
			_fullProbeDone = true;
			int num = (flag ? componentsInChildren.Length : Math.Min(20, componentsInChildren.Length));
			for (int j = 0; j < num; j++)
			{
				list.Add($"    [{j}] {((Object)componentsInChildren[j]).name}");
			}
			if (flag)
			{
				list.Add($"  root tag='{gameObject.tag}' layer={LayerMask.LayerToName(gameObject.layer)}({gameObject.layer})");
				Collider[] componentsInChildren2 = gameObject.GetComponentsInChildren<Collider>(true);
				foreach (Collider val3 in componentsInChildren2)
				{
					if (!((Object)(object)val3 == (Object)null))
					{
						list.Add($"  col: '{((Object)val3).name}' {((object)val3).GetType().Name} tag='{((Component)val3).tag}' layer={LayerMask.LayerToName(((Component)val3).gameObject.layer)} trig={val3.isTrigger}");
					}
				}
				try
				{
					LayerMask val4 = GameInfo.ProjectileHitLayer;
					object arg = ((LayerMask)(ref val4)).value;
					val4 = GameInfo.NpcProjectileHitLayer;
					list.Add($"  masks: projHit={arg} npcProjHit={((LayerMask)(ref val4)).value}");
					PropertyInfo[] properties = typeof(GameInfo).GetProperties(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
					foreach (PropertyInfo propertyInfo in properties)
					{
						if (!(propertyInfo.PropertyType == typeof(LayerMask)) || !propertyInfo.Name.ToLower().Contains("layer"))
						{
							continue;
						}
						object obj2 = propertyInfo.GetValue(null);
						if (obj2 == null)
						{
							val4 = default(LayerMask);
							obj2 = val4;
						}
						LayerMask val5 = (LayerMask)obj2;
						List<string> list2 = new List<string>();
						for (int m = 0; m < 32; m++)
						{
							if ((((LayerMask)(ref val5)).value & (1 << m)) != 0)
							{
								string text = LayerMask.LayerToName(m);
								list2.Add(string.IsNullOrEmpty(text) ? m.ToString() : $"{m}:{text}");
							}
						}
						list.Add(string.Format("  mask {0}={1} [{2}]", propertyInfo.Name, ((LayerMask)(ref val5)).value, string.Join(",", list2)));
					}
				}
				catch (Exception ex)
				{
					list.Add("  masks fail: " + ex.Message);
				}
				HashSet<string> hashSet = new HashSet<string>();
				Component[] componentsInChildren3 = gameObject.GetComponentsInChildren<Component>(true);
				foreach (Component val6 in componentsInChildren3)
				{
					if (!((Object)(object)val6 == (Object)null))
					{
						hashSet.Add(((object)val6).GetType().FullName ?? ((object)val6).GetType().Name);
					}
				}
				list.Add($"  components={hashSet.Count}");
				foreach (string item2 in hashSet)
				{
					list.Add("    comp: " + item2);
				}
			}
			foreach (string item3 in list)
			{
				Plugin.Log.LogInfo((object)item3);
			}
		}
	}
	internal sealed class NpcWalker : MonoBehaviour
	{
		private Vector3 _home;

		private Quaternion _homeRot = Quaternion.identity;

		private Vector3 _target;

		private float _idleTimer;

		private bool _hasTarget;

		private float _walkPhase;

		private Vector3 _velocity;

		private Vector3 _lastPos;

		private float _nextDiagLog;

		private Rigidbody? _rb;

		private bool _ownBody;

		private CapsuleCollider? _col;

		private bool _ownCollider;

		private bool _grounded;

		private float _groundY;

		private float _climbTime;

		private const float StepHeight = 0.45f;

		private const float StepLiftSpeed = 2.2f;

		private float _stuckTime;

		private float _veerYaw;

		private Vector3? _faceLock;

		private int _pickFails;

		private Random? _rng;

		private bool _retire;

		private bool _retiredDone;

		private float _nextPartyHop;

		private float _spinLeft;

		private bool _vanillaFrozen;

		private float _nextEyeFix;

		private const float TurnSpeed = 120f;

		private const float Accel = 12f;

		private const float MaxStepY = 1.2f;

		private Transform? _body;

		private Transform? _armL;

		private Transform? _armR;

		private Transform? _armLowL;

		private Transform? _armLowR;

		private Transform? _head;

		private Transform? _legL;

		private Transform? _legR;

		private Transform? _shinL;

		private Transform? _shinR;

		private Vector3 _bodyOrigPos;

		private Quaternion _bodyOrigRot = Quaternion.identity;

		private Quaternion _armLOrig = Quaternion.identity;

		private Quaternion _armROrig = Quaternion.identity;

		private Quaternion _armLowLOrig = Quaternion.identity;

		private Quaternion _armLowROrig = Quaternion.identity;

		private Quaternion _headOrig = Quaternion.identity;

		private Quaternion _legLOrig = Quaternion.identity;

		private Quaternion _legROrig = Quaternion.identity;

		private Quaternion _shinLOrig = Quaternion.identity;

		private Quaternion _shinROrig = Quaternion.identity;

		private Transform? _handBoneL;

		private Transform? _handBoneR;

		private readonly List<(Transform t, Transform? parent, Vector3 pos, Quaternion rot)> _reparented = new List<(Transform, Transform, Vector3, Quaternion)>();

		private readonly List<Behaviour> _ikLocks = new List<Behaviour>();

		private float _idleStillTime;

		private static FieldInfo? _eyePosField;

		private static FieldInfo? _eyesField;

		internal bool Retired => _retire;

		internal bool RetiredDone => _retiredDone;

		private void Start()
		{
			//IL_0007: 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_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			_home = ((Component)this).transform.position;
			_homeRot = ((Component)this).transform.rotation;
			_lastPos = ((Component)this).transform.position;
			_rng = new Random(StableSeed(((Object)this).name));
			_idleTimer = RngRange(Plugin.IdleMin.Value, Plugin.IdleMax.Value);
			_walkPhase = RngRange(0f, MathF.PI * 2f);
			_nextPartyHop = Time.time + RngRange(2f, 4f);
			CacheRig();
			DisableArmIkLocks();
			EnsurePhysics();
			if (!Plugin.Enabled.Value)
			{
				TeleportHome();
			}
			Plugin.Log.LogInfo((object)($"[NpcWalker] start '{((Object)this).name}' home={_home} body={(Object)(object)_body != (Object)null} armL={(Object)(object)_armL != (Object)null} armR={(Object)(object)_armR != (Object)null} " + $"rb={(Object)(object)_rb != (Object)null} col={(Object)(object)_col != (Object)null} ownBody={_ownBody}"));
		}

		public void TeleportHome()
		{
			//IL_0057: 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_0069: 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_0014: 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_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: 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_007f: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if ((Object)(object)_rb != (Object)null)
				{
					_rb.linearVelocity = Vector3.zero;
					_rb.angularVelocity = Vector3.zero;
					_rb.MovePosition(_home);
					_rb.MoveRotation(_homeRot);
				}
				((Component)this).transform.SetPositionAndRotation(_home, _homeRot);
				_lastPos = _home;
			}
			catch
			{
			}
			_target = _home;
			_hasTarget = false;
			_stuckTime = 0f;
			_idleTimer = RngRange(Plugin.IdleMin.Value, Plugin.IdleMax.Value);
			RestoreBonePose();
			SetIkLocks(on: true);
			_vanillaFrozen = true;
		}

		private void EnsurePhysics()
		{
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Expected O, but got Unknown
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			CapsuleCollider val = null;
			CapsuleCollider[] componentsInChildren = ((Component)this).GetComponentsInChildren<CapsuleCollider>(true);
			foreach (CapsuleCollider val2 in componentsInChildren)
			{
				if ((Object)(object)val2 != (Object)null && !((Collider)val2).isTrigger)
				{
					val = val2;
					break;
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				string text = "NPC";
				int layer = ((Component)this).gameObject.layer;
				Transform[] componentsInChildren2 = ((Component)this).GetComponentsInChildren<Transform>(true);
				foreach (Transform val3 in componentsInChildren2)
				{
					if ((Object)(object)val3 != (Object)null && (Object)(object)val3 != (Object)(object)((Component)this).transform && ((Component)val3).CompareTag("NPC"))
					{
						text = ((Component)val3).tag;
						layer = ((Component)val3).gameObject.layer;
						break;
					}
				}
				GameObject val4 = new GameObject("NpcWalkBody");
				val4.tag = text;
				val4.layer = layer;
				val4.transform.SetParent(((Component)this).transform, false);
				val4.transform.localPosition = Vector3.zero;
				CapsuleCollider val5 = val4.AddComponent<CapsuleCollider>();
				val5.height = 1.7f;
				val5.radius = 0.32f;
				val5.center = new Vector3(0f, 0.9f, 0f);
				((Collider)val5).isTrigger = false;
				_ownCollider = true;
				val = val5;
				Plugin.Log.LogInfo((object)$"[NpcWalker] '{((Object)this).name}': added solid body tag='{text}' layer={layer}");
			}
			_col = val;
			_rb = ((Component)this).GetComponent<Rigidbody>();
			if ((Object)(object)_rb == (Object)null)
			{
				_rb = ((Component)this).gameObject.AddComponent<Rigidbody>();
				_ownBody = true;
			}
			_rb.mass = 70f;
			_rb.linearDamping = 0f;
			_rb.angularDamping = 10f;
			_rb.collisionDetectionMode = (CollisionDetectionMode)0;
			_rb.interpolation = (RigidbodyInterpolation)1;
			_rb.constraints = (RigidbodyConstraints)112;
		}

		private void DisableArmIkLocks()
		{
			Behaviour[] componentsInChildren = ((Component)this).GetComponentsInChildren<Behaviour>(true);
			foreach (Behaviour val in componentsInChildren)
			{
				if ((Object)(object)val == (Object)null || val is NpcWalker)
				{
					continue;
				}
				string text = ((object)val).GetType().FullName ?? ((object)val).GetType().Name;
				if (text.IndexOf("ik", StringComparison.OrdinalIgnoreCase) >= 0 && !(val is Animator) && !(val is Animation))
				{
					if (!_ikLocks.Contains(val))
					{
						_ikLocks.Add(val);
					}
					try
					{
						val.enabled = false;
						Plugin.Log.LogInfo((object)("[NpcWalker] '" + ((Object)this).name + "': disabled arm lock '" + text + "' on '" + ((Object)val).name + "'"));
					}
					catch (Exception ex)
					{
						Plugin.Log.LogWarning((object)("[NpcWalker] disable '" + text + "' fail: " + ex.Message));
					}
				}
			}
		}

		private void SetIkLocks(bool on)
		{
			foreach (Behaviour ikLock in _ikLocks)
			{
				if ((Object)(object)ikLock == (Object)null)
				{
					continue;
				}
				try
				{
					if (ikLock.enabled != on)
					{
						ikLock.enabled = on;
					}
				}
				catch
				{
				}
			}
		}

		private void OnDestroy()
		{
			SetIkLocks(on: true);
			RestorePose();
			try
			{
				if (_ownBody && (Object)(object)_rb != (Object)null)
				{
					Object.Destroy((Object)(object)_rb);
				}
				if (_ownCollider && (Object)(object)_col != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)_col).gameObject);
				}
			}
			catch
			{
			}
		}

		public void Die()
		{
			try
			{
				if (_ownBody && (Object)(object)_rb != (Object)null)
				{
					Object.Destroy((Object)(object)_rb);
				}
				if (_ownCollider && (Object)(object)_col != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)_col).gameObject);
				}
			}
			catch
			{
			}
			_rb = null;
			_col = null;
			((Behaviour)this).enabled = false;
		}

		private void CacheRig()
		{
			//IL_008a: 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_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: 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_0117: 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_0136: 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_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: 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_01ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: 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_021c: 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)
			_body = FindDeep("Body") ?? FindDeep("Character");
			_armL = FindDeep("ArmUpper_L");
			_armR = FindDeep("ArmUpper_R");
			_armLowL = FindDeep("ArmLower_L");
			_armLowR = FindDeep("ArmLower_R");
			_head = FindDeep("Head");
			if ((Object)(object)_body != (Object)null)
			{
				_bodyOrigPos = _body.localPosition;
				_bodyOrigRot = _body.localRotation;
			}
			if ((Object)(object)_armL != (Object)null)
			{
				_armLOrig = _armL.localRotation;
			}
			if ((Object)(object)_armR != (Object)null)
			{
				_armROrig = _armR.localRotation;
			}
			if ((Object)(object)_armLowL != (Object)null)
			{
				_armLowLOrig = _armLowL.localRotation;
			}
			if ((Object)(object)_armLowR != (Object)null)
			{
				_armLowROrig = _armLowR.localRotation;
			}
			if ((Object)(object)_head != (Object)null)
			{
				_headOrig = _head.localRotation;
			}
			_legL = FindDeep("LegUpper_L");
			_legR = FindDeep("LegUpper_R");
			_shinL = FindDeep("LegLower_L");
			_shinR = FindDeep("LegLower_R");
			if ((Object)(object)_legL != (Object)null)
			{
				_legLOrig = _legL.localRotation;
			}
			if ((Object)(object)_legR != (Object)null && (Object)(object)_legR != (Object)(object)_legL)
			{
				_legROrig = _legR.localRotation;
			}
			if ((Object)(object)_shinL != (Object)null)
			{
				_shinLOrig = _shinL.localRotation;
			}
			if ((Object)(object)_shinR != (Object)null && (Object)(object)_shinR != (Object)(object)_shinL)
			{
				_shinROrig = _shinR.localRotation;
			}
			ManualLogSource log = Plugin.Log;
			string[] obj = new string[10]
			{
				"[NpcWalker] rig '",
				((Object)this).name,
				"': legL=",
				null,
				null,
				null,
				null,
				null,
				null,
				null
			};
			Transform? legL = _legL;
			obj[3] = ((legL != null) ? ((Object)legL).name : null) ?? "none";
			obj[4] = " legR=";
			Transform? legR = _legR;
			obj[5] = ((legR != null) ? ((Object)legR).name : null) ?? "none";
			obj[6] = " shinL=";
			Transform? shinL = _shinL;
			obj[7] = ((shinL != null) ? ((Object)shinL).name : null) ?? "none";
			obj[8] = " shinR=";
			Transform? shinR = _shinR;
			obj[9] = ((shinR != null) ? ((Object)shinR).name : null) ?? "none";
			log.LogInfo((object)string.Concat(obj));
			CacheHandGlue();
		}

		private void CacheHandGlue()
		{
			_handBoneL = FindDeep("Hand_L");
			_handBoneR = FindDeep("Hand_R");
			AttachDeco(_handBoneL, FindDeep("HandLeft"), FindDeep("LeftHand"));
			AttachDeco(_handBoneR, FindDeep("HandRight"), FindDeep("RightHand"));
			ManualLogSource log = Plugin.Log;
			string[] obj = new string[8]
			{
				"[NpcWalker] hands '",
				((Object)this).name,
				"': boneL=",
				null,
				null,
				null,
				null,
				null
			};
			Transform? handBoneL = _handBoneL;
			obj[3] = ((handBoneL != null) ? ((Object)handBoneL).name : null) ?? "none";
			obj[4] = " boneR=";
			Transform? handBoneR = _handBoneR;
			obj[5] = ((handBoneR != null) ? ((Object)handBoneR).name : null) ?? "none";
			obj[6] = " ";
			obj[7] = $"reparented={_reparented.Count}";
			log.LogInfo((object)string.Concat(obj));
		}

		private void AttachDeco(Transform? handBone, params Transform?[] candidates)
		{
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)handBone == (Object)null)
			{
				return;
			}
			List<Transform> list = new List<Transform>();
			foreach (Transform val in candidates)
			{
				if ((Object)(object)val == (Object)null || (Object)(object)val == (Object)(object)handBone)
				{
					continue;
				}
				bool flag = false;
				foreach (Transform val2 in candidates)
				{
					if ((Object)(object)val2 != (Object)null && (Object)(object)val2 != (Object)(object)val && val.IsChildOf(val2))
					{
						flag = true;
						break;
					}
				}
				if (!flag)
				{
					list.Add(val);
				}
			}
			foreach (Transform item in list)
			{
				try
				{
					_reparented.Add((item, item.parent, item.localPosition, item.localRotation));
					item.SetParent(handBone, true);
					Plugin.Log.LogInfo((object)("[NpcWalker] '" + ((Object)this).name + "': hand chain '" + ((Object)item).name + "' attached to '" + ((Object)handBone).name + "'"));
				}
				catch (Exception ex)
				{
					Plugin.Log.LogWarning((object)("[NpcWalker] attach '" + ((Object)item).name + "' fail: " + ex.Message));
				}
			}
		}

		private Transform? FindByPart(params string[] parts)
		{
			Transform[] componentsInChildren = ((Component)this).GetComponentsInChildren<Transform>(true);
			foreach (Transform val in componentsInChildren)
			{
				string text = ((Object)val).name.ToLowerInvariant().Replace("_", "").Replace("-", "")
					.Replace(" ", "");
				foreach (string value in parts)
				{
					if (text.Contains(value))
					{
						return val;
					}
				}
			}
			return null;
		}

		private Transform? FindLastByPart(params string[] parts)
		{
			Transform result = null;
			Transform[] componentsInChildren = ((Component)this).GetComponentsInChildren<Transform>(true);
			foreach (Transform val in componentsInChildren)
			{
				string text = ((Object)val).name.ToLowerInvariant().Replace("_", "").Replace("-", "")
					.Replace(" ", "");
				foreach (string value in parts)
				{
					if (text.Contains(value))
					{
						result = val;
					}
				}
			}
			return result;
		}

		public void GoHomeAndStop()
		{
			_retire = true;
			TeleportHome();
			_retiredDone = true;
		}

		private bool Homing()
		{
			if (!Plugin.Enabled.Value)
			{
				return !_retiredDone;
			}
			return false;
		}

		private void RefreshEyeAnchor()
		{
			//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_00da: 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_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: 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_010b: 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_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: 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_012b: Unknown result type (might be due to invalid IL or missing references)
			if (Time.time < _nextEyeFix)
			{
				return;
			}
			_nextEyeFix = Time.time + 0.2f;
			try
			{
				Type typeFromHandle = typeof(NPC);
				if ((object)_eyePosField == null)
				{
					_eyePosField = typeFromHandle.GetField("_eyePos", BindingFlags.Instance | BindingFlags.NonPublic);
				}
				if ((object)_eyesField == null)
				{
					_eyesField = typeFromHandle.GetField("_eyes", BindingFlags.Instance | BindingFlags.NonPublic);
				}
				if (_eyePosField == null || _eyesField == null)
				{
					return;
				}
				NPC component = ((Component)this).GetComponent<NPC>();
				if ((Object)(object)component == (Object)null || !(_eyesField.GetValue(component) is Transform[] array) || array.Length == 0 || (Object)(object)array[0] == (Object)null)
				{
					return;
				}
				Vector3 val = Vector3.zero;
				int num = 0;
				Transform[] array2 = array;
				foreach (Transform val2 in array2)
				{
					if (!((Object)(object)val2 == (Object)null))
					{
						val += val2.position;
						num++;
					}
				}
				if (num != 0)
				{
					val /= (float)num;
					val -= array[0].up * 0.3f;
					_eyePosField.SetValue(component, val);
				}
			}
			catch
			{
			}
		}

		private static int StableSeed(string name)
		{
			//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)
			uint num = 2166136261u;
			Scene activeScene = SceneManager.GetActiveScene();
			string text = name + "@" + ((Scene)(ref activeScene)).name;
			string text2 = text;
			foreach (char c in text2)
			{
				num ^= c;
				num *= 16777619;
			}
			return (int)num;
		}

		private float RngRange(float a, float b)
		{
			return (float)((double)a + (_rng?.NextDouble() ?? 0.5) * (double)(b - a));
		}

		private bool RngChance(double p)
		{
			return (_rng?.NextDouble() ?? 0.5) < p;
		}

		private int RngSign()
		{
			if (!((_rng?.NextDouble() ?? 0.5) < 0.5))
			{
				return 1;
			}
			return -1;
		}

		private float RngAngle(float magnitude)
		{
			return (float)((_rng?.NextDouble() ?? 0.5) * 2.0 - 1.0) * magnitude;
		}

		private Transform? FindDeep(string n)
		{
			Transform[] componentsInChildren = ((Component)this).GetComponentsInChildren<Transform>(true);
			foreach (Transform val in componentsInChildren)
			{
				if (((Object)val).name == n)
				{
					return val;
				}
			}
			return null;
		}

		private void Update()
		{
			//IL_0016: 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_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_0042: 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_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_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			float deltaTime = Time.deltaTime;
			if (deltaTime <= 0f)
			{
				return;
			}
			_velocity = (((Component)this).transform.position - _lastPos) / Mathf.Max(deltaTime, 0.0001f);
			_lastPos = ((Component)this).transform.position;
			Vector3 val = new Vector3(_velocity.x, 0f, _velocity.z);
			float magnitude = ((Vector3)(ref val)).magnitude;
			RefreshEyeAnchor();
			if ((Object)(object)_rb == (Object)null)
			{
				ApplyIdle(deltaTime);
				return;
			}
			if (Homing() || _retire)
			{
				if (!_vanillaFrozen)
				{
					TeleportHome();
				}
				if (_retire)
				{
					_retiredDone = true;
				}
				SetIkLocks(on: true);
			}
			else if (magnitude < 0.15f)
			{
				ApplyIdle(deltaTime);
				_idleStillTime += deltaTime;
				if (_idleStillTime > 1.5f)
				{
					SetIkLocks(on: true);
				}
			}
			else
			{
				_idleStillTime = 0f;
				SetIkLocks(on: false);
				ApplyWalk(deltaTime);
			}
			if (Time.unscaledTime >= _nextDiagLog)
			{
				_nextDiagLog = Time.unscaledTime + 15f;
				Plugin.Log.LogInfo((object)($"[NpcWalker] '{((Object)this).name}' pos={((Component)this).transform.position} home={_home} hasTarget={_hasTarget} " + $"idle={_idleTimer:F1} spd={magnitude:F2} grounded={_grounded} stuck={_stuckTime:F1} veer={_veerYaw:F0} fails={_pickFails}"));
			}
		}

		private void FixedUpdate()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: 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_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_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: 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_01ba: 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_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: 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_0238: Unknown result type (might be due to invalid IL or missing references)
			//IL_023d: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_035a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0365: Unknown result type (might be due to invalid IL or missing references)
			//IL_036a: Unknown result type (might be due to invalid IL or missing references)
			//IL_036f: Unknown result type (might be due to invalid IL or missing references)
			//IL_031f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0320: Unknown result type (might be due to invalid IL or missing references)
			//IL_0330: 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_033c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0342: Unknown result type (might be due to invalid IL or missing references)
			//IL_0348: Unknown result type (might be due to invalid IL or missing references)
			//IL_034e: Unknown result type (might be due to invalid IL or missing references)
			//IL_025b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0260: Unknown result type (might be due to invalid IL or missing references)
			//IL_0265: Unknown result type (might be due to invalid IL or missing references)
			//IL_026a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0278: Unknown result type (might be due to invalid IL or missing references)
			//IL_027d: Unknown result type (might be due to invalid IL or missing references)
			//IL_028a: Unknown result type (might be due to invalid IL or missing references)
			//IL_029a: Unknown result type (might be due to invalid IL or missing references)
			//IL_029f: 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_0407: Unknown result type (might be due to invalid IL or missing references)
			//IL_0412: Unknown result type (might be due to invalid IL or missing references)
			//IL_0418: Unknown result type (might be due to invalid IL or missing references)
			//IL_041d: Unknown result type (might be due to invalid IL or missing references)
			//IL_038c: Unknown result type (might be due to invalid IL or missing references)
			//IL_038d: Unknown result type (might be due to invalid IL or missing references)
			//IL_039d: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03af: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0301: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_04fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0502: Unknown result type (might be due to invalid IL or missing references)
			//IL_0517: Unknown result type (might be due to invalid IL or missing references)
			//IL_051c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0521: Unknown result type (might be due to invalid IL or missing references)
			//IL_052f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0534: Unknown result type (might be due to invalid IL or missing references)
			//IL_0541: Unknown result type (might be due to invalid IL or missing references)
			//IL_0572: Unknown result type (might be due to invalid IL or missing references)
			//IL_0577: Unknown result type (might be due to invalid IL or missing references)
			//IL_0581: Unknown result type (might be due to invalid IL or missing references)
			//IL_0586: Unknown result type (might be due to invalid IL or missing references)
			//IL_0591: Unknown result type (might be due to invalid IL or missing references)
			//IL_059b: Unknown result type (might be due to invalid IL or missing references)
			//IL_05a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_05a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_05a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0801: Unknown result type (might be due to invalid IL or missing references)
			//IL_0810: Unknown result type (might be due to invalid IL or missing references)
			//IL_0815: Unknown result type (might be due to invalid IL or missing references)
			//IL_0817: Unknown result type (might be due to invalid IL or missing references)
			//IL_0818: Unknown result type (might be due to invalid IL or missing references)
			//IL_0825: Unknown result type (might be due to invalid IL or missing references)
			//IL_082a: Unknown result type (might be due to invalid IL or missing references)
			//IL_082b: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0866: Unknown result type (might be due to invalid IL or missing references)
			//IL_086b: Unknown result type (might be due to invalid IL or missing references)
			//IL_087b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0880: Unknown result type (might be due to invalid IL or missing references)
			//IL_066d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0672: Unknown result type (might be due to invalid IL or missing references)
			//IL_067c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0681: Unknown result type (might be due to invalid IL or missing references)
			//IL_068c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0696: Unknown result type (might be due to invalid IL or missing references)
			//IL_069b: Unknown result type (might be due to invalid IL or missing references)
			//IL_06a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_06a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_06aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0938: Unknown result type (might be due to invalid IL or missing references)
			//IL_0940: Unknown result type (might be due to invalid IL or missing references)
			//IL_0946: Unknown result type (might be due to invalid IL or missing references)
			//IL_0903: Unknown result type (might be due to invalid IL or missing references)
			//IL_0914: Unknown result type (might be due to invalid IL or missing references)
			//IL_0919: Unknown result type (might be due to invalid IL or missing references)
			//IL_06dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_06e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_06f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_06f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_06fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0706: Unknown result type (might be due to invalid IL or missing references)
			//IL_070b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0710: Unknown result type (might be due to invalid IL or missing references)
			//IL_0712: Unknown result type (might be due to invalid IL or missing references)
			//IL_0714: Unknown result type (might be due to invalid IL or missing references)
			//IL_0734: Unknown result type (might be due to invalid IL or missing references)
			//IL_0739: Unknown result type (might be due to invalid IL or missing references)
			//IL_074c: Unknown result type (might be due to invalid IL or missing references)
			//IL_075c: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_rb == (Object)null)
			{
				return;
			}
			GroundCheckFixed();
			if (((Component)this).transform.position.y < -30f || ((Component)this).transform.position.y < _home.y - 4f)
			{
				Plugin.Log.LogWarning((object)$"[NpcWalker] '{((Object)this).name}' fell out of world ({((Component)this).transform.position.y:F1} vs home {_home.y:F1}), rescuing home");
				_rb.linearVelocity = Vector3.zero;
				_rb.MovePosition(_home + Vector3.up * 1f);
				((Component)this).transform.SetPositionAndRotation(_home + Vector3.up * 1f, _homeRot);
				_hasTarget = false;
				_idleTimer = RngRange(Plugin.IdleMin.Value, Plugin.IdleMax.Value);
				return;
			}
			if (!Homing() && !_retire && (((Component)this).transform.position.y < _home.y - 1.2f || (WaterY() > -999f && ((Component)this).transform.position.y < WaterY() + 0.1f)))
			{
				_target = _home;
				_target.y = ((Component)this).transform.position.y;
				_hasTarget = true;
				_stuckTime = 0f;
			}
			Vector3 linearVelocity = _rb.linearVelocity;
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor(linearVelocity.x, 0f, linearVelocity.z);
			if (!_hasTarget && !Homing() && !_retire)
			{
				_idleTimer -= Time.fixedDeltaTime;
				if (_idleTimer <= 0f && !_faceLock.HasValue)
				{
					PickTarget();
				}
			}
			if (_faceLock.HasValue)
			{
				Vector3 value = _faceLock.Value;
				value.y = 0f;
				if (((Vector3)(ref value)).sqrMagnitude > 0.001f)
				{
					Quaternion val2 = Quaternion.LookRotation(((Vector3)(ref value)).normalized, Vector3.up);
					_rb.MoveRotation(Quaternion.RotateTowards(_rb.rotation, val2, 180f * Time.fixedDeltaTime));
					if (Quaternion.Angle(_rb.rotation, val2) < 12f)
					{
						_faceLock = null;
						_idleTimer = 0.2f;
					}
				}
				else
				{
					_faceLock = null;
				}
				val = Vector3.MoveTowards(val, Vector3.zero, 18f * Time.fixedDeltaTime);
				_rb.linearVelocity = new Vector3(val.x, linearVelocity.y, val.z);
				_stuckTime = 0f;
				return;
			}
			if (!_hasTarget)
			{
				val = Vector3.MoveTowards(val, Vector3.zero, 14.400001f * Time.fixedDeltaTime);
				_rb.linearVelocity = new Vector3(val.x, linearVelocity.y, val.z);
				return;
			}
			Vector3 val3 = _target - ((Component)this).transform.position;
			val3.y = 0f;
			float magnitude = ((Vector3)(ref val3)).magnitude;
			if (magnitude < 0.5f)
			{
				val = Vector3.MoveTowards(val, Vector3.zero, 14.400001f * Time.fixedDeltaTime);
				_rb.linearVelocity = new Vector3(val.x, linearVelocity.y, val.z);
				_stuckTime = 0f;
				_hasTarget = false;
				_idleTimer = RngRange(Plugin.IdleMin.Value, Plugin.IdleMax.Value);
				if (_retire)
				{
					_retiredDone = true;
				}
				return;
			}
			Vector3 val4 = new Vector3(linearVelocity.x, 0f, linearVelocity.z);
			float magnitude2 = ((Vector3)(ref val4)).magnitude;
			if (_grounded && magnitude2 < 0.2f)
			{
				_stuckTime += Time.fixedDeltaTime;
			}
			else
			{
				_stuckTime = 0f;
			}
			if (_stuckTime > 1.5f)
			{
				_stuckTime = 0f;
				_hasTarget = false;
				_idleTimer = RngRange(0.4f, 1f);
				_veerYaw += (float)RngSign() * RngRange(90f, 150f);
				_veerYaw = Mathf.DeltaAngle(0f, _veerYaw);
				_pickFails = 99;
				return;
			}
			_veerYaw = Mathf.Clamp(Mathf.DeltaAngle(0f, _veerYaw), -70f, 70f);
			Quaternion val5 = Quaternion.LookRotation(val3 / magnitude, Vector3.up) * Quaternion.Euler(0f, _veerYaw, 0f);
			_rb.MoveRotation(Quaternion.RotateTowards(_rb.rotation, val5, 120f * Time.fixedDeltaTime));
			_veerYaw = Mathf.MoveTowards(_veerYaw, 0f, 150f * Time.fixedDeltaTime);
			Vector3 val6 = ((Component)this).transform.position + Vector3.up * 0.45f + ((Component)this).transform.forward * 0.2f;
			RaycastHit val7 = default(RaycastHit);
			if (Physics.SphereCast(val6, 0.3f, ((Component)this).transform.forward, ref val7, 0.8f, -1, (QueryTriggerInteraction)1) && !IsSelf(((RaycastHit)(ref val7)).transform))
			{
				if (((RaycastHit)(ref val7)).distance < 0.45f)
				{
					_faceLock = EscapeDir(out var _);
					_hasTarget = false;
					_idleTimer = 0.2f;
					_stuckTime = 0f;
					_veerYaw = 0f;
					return;
				}
				if (IsPlayer(((RaycastHit)(ref val7)).transform))
				{
					_veerYaw += (float)RngSign() * 25f;
					_stuckTime = 0f;
				}
				else
				{
					Vector3 val8 = ((Component)this).transform.position + Vector3.up * 1.55f + ((Component)this).transform.forward * 0.35f;
					RaycastHit val9 = default(RaycastHit);
					bool flag = !Physics.Raycast(val8, ((Component)this).transform.forward, ref val9, 0.75f, -1, (QueryTriggerInteraction)1) || IsPlayer(((RaycastHit)(ref val9)).transform);
					float num = float.NegativeInfinity;
					Vector3 val10 = ((Component)this).transform.position + ((Component)this).transform.forward * 0.55f + Vector3.up * 0.6f;
					RaycastHit[] array = Physics.RaycastAll(val10, Vector3.down, 1.5f, -1, (QueryTriggerInteraction)1);
					RaycastHit[] array2 = array;
					for (int i = 0; i < array2.Length; i++)
					{
						RaycastHit val11 = array2[i];
						if (!IsSelf(((RaycastHit)(ref val11)).transform) && ((RaycastHit)(ref val11)).point.y > num)
						{
							num = ((RaycastHit)(ref val11)).point.y;
						}
					}
					float num2 = num - _groundY;
					if (_grounded && flag && num2 > 0.05f && num2 <= 0.45f)
					{
						_climbTime = 0.45f;
					}
					else if (!flag || num2 > 0.45f)
					{
						_hasTarget = false;
						_idleTimer = RngRange(0.3f, 0.8f);
						_veerYaw += (float)RngSign() * RngRange(60f, 120f);
						return;
					}
				}
			}
			Vector3 val12 = ((Component)this).transform.forward * Plugin.WalkSpeed.Value;
			val = Vector3.MoveTowards(val, val12, 12f * Time.fixedDeltaTime);
			float y = linearVelocity.y;
			if (_climbTime > 0f && _grounded)
			{
				_climbTime -= Time.fixedDeltaTime;
				_rb.MovePosition(_rb.position + Vector3.up * (2.2f * Time.fixedDeltaTime));
			}
			if (Plugin.PartyMode.Value && _grounded && Time.time >= _nextPartyHop)
			{
				_nextPartyHop = Time.time + RngRange(1.5f, 3.5f);
				_spinLeft = 360f;
			}
			if (_spinLeft > 0f)
			{
				float num3 = Mathf.Min(_spinLeft, 720f * Time.fixedDeltaTime);
				_rb.MoveRotation(_rb.rotation * Quaternion.Euler(0f, num3, 0f));
				_spinLeft -= num3;
			}
			_rb.linearVelocity = new Vector3(val.x, y, val.z);
		}

		private void GroundCheckFixed()
		{
			//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_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: 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_0078: 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_00a3: Unknown result type (might be due to invalid IL or missing references)
			_grounded = false;
			if ((Object)(object)_col == (Object)null)
			{
				return;
			}
			Vector3 val = ((Component)this).transform.position + Vector3.up * (_col.radius + 0.35f);
			RaycastHit val2 = default(RaycastHit);
			if (Physics.SphereCast(val, _col.radius * 0.9f, Vector3.down, ref val2, 0.8f, -1, (QueryTriggerInteraction)1) && !IsSelf(((RaycastHit)(ref val2)).transform))
			{
				float num = Vector3.Angle(Vector3.up, ((RaycastHit)(ref val2)).normal);
				_grounded = num < 50f;
				if (_grounded)
				{
					_groundY = ((RaycastHit)(ref val2)).point.y;
				}
			}
		}

		private void PickTarget()
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: 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)
			//IL_0038: 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_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)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: 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_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: 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_0193: 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_019c: 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_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//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_01ae: 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_01b8: 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)
			_vanillaFrozen = false;
			float num = Mathf.Max(2f, Plugin.WanderRadius.Value * 2f);
			Vector3 val = ((Component)this).transform.position - _home;
			val.y = 0f;
			for (int i = 0; i < 4; i++)
			{
				Vector3 val3;
				if (((Vector3)(ref val)).magnitude > num)
				{
					Vector3 val2 = -((Vector3)(ref val)).normalized * RngRange(1.5f, 3f);
					val2 = Quaternion.Euler(0f, RngAngle(40f), 0f) * val2;
					val3 = ((Component)this).transform.position + val2;
				}
				else if (i < 3 && RngChance(0.699999988079071))
				{
					float num2 = RngAngle(65f);
					float num3 = RngRange(0.8f, Mathf.Max(1f, Plugin.WanderRadius.Value));
					val3 = ((Component)this).transform.position + Quaternion.Euler(0f, num2, 0f) * ((Component)this).transform.forward * num3;
				}
				else
				{
					float num4 = RngRange(0f, MathF.PI * 2f);
					float num5 = RngRange(0.8f, Mathf.Max(1f, Plugin.WanderRadius.Value));
					val3 = ((Component)this).transform.position + new Vector3(Mathf.Cos(num4) * num5, 0f, Mathf.Sin(num4) * num5);
				}
				if (HasGroundNear(val3, ((Component)this).transform.position.y) && WalkOutClear(val3))
				{
					_target = val3;
					_target.y = ((Component)this).transform.position.y;
					_hasTarget = true;
					_stuckTime = 0f;
					_pickFails = 0;
					return;
				}
			}
			_pickFails++;
			if (_pickFails >= 3)
			{
				_pickFails = 0;
				if (TryEscape())
				{
					return;
				}
			}
			_hasTarget = false;
			_idleTimer = RngRange(0.4f, 0.9f);
			_veerYaw += RngRange(90f, 150f);
		}

		private Vector3 EscapeDir(out float clearDist)
		{
			//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_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_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_005b: 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_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: 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)
			Vector3 val = ((Component)this).transform.position + Vector3.up * 0.9f;
			float num = 0f;
			Vector3 result = -((Component)this).transform.forward;
			RaycastHit val3 = default(RaycastHit);
			for (int i = 0; i < 8; i++)
			{
				float num2 = (float)i * 45f;
				Vector3 val2 = Quaternion.Euler(0f, num2, 0f) * Vector3.forward;
				float num3 = 1.6f;
				if (Physics.SphereCast(val, 0.3f, val2, ref val3, 1.6f, -1, (QueryTriggerInteraction)1) && !IsSelf(((RaycastHit)(ref val3)).transform))
				{
					num3 = Mathf.Max(0f, ((RaycastHit)(ref val3)).distance - 0.35f);
				}
				if (num3 > num)
				{
					num = num3;
					result = val2;
				}
			}
			clearDist = num;
			return result;
		}

		private bool TryEscape()
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0071: 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)
			float clearDist;
			Vector3 val = EscapeDir(out clearDist);
			if (clearDist < 0.35f)
			{
				Plugin.Log.LogInfo((object)("[NpcWalker] '" + ((Object)this).name + "' fully boxed in, waiting"));
				_hasTarget = false;
				_idleTimer = RngRange(3f, 6f);
				return true;
			}
			_target = ((Component)this).transform.position + val * Mathf.Min(clearDist, 1.6f);
			_target.y = ((Component)this).transform.position.y;
			_hasTarget = true;
			_stuckTime = 0f;
			return true;
		}

		private bool WalkOutClear(Vector3 candidate)
		{
			//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_0020: 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_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: 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_0068: 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)
			Vector3 val = ((Component)this).transform.position + Vector3.up * 0.9f;
			Vector3 val2 = candidate - ((Component)this).transform.position;
			val2.y = 0f;
			float num = Mathf.Min(((Vector3)(ref val2)).magnitude, 1.2f);
			if (num < 0.2f)
			{
				return false;
			}
			val2 /= ((Vector3)(ref val2)).magnitude;
			RaycastHit val3 = default(RaycastHit);
			if (Physics.SphereCast(val, 0.3f, val2, ref val3, num, -1, (QueryTriggerInteraction)1) && !IsSelf(((RaycastHit)(ref val3)).transform))
			{
				return false;
			}
			return true;
		}

		private bool IsSelf(Transform? t)
		{
			if ((Object)(object)t == (Object)null)
			{
				return false;
			}
			if (!((Object)(object)t == (Object)(object)((Component)this).transform))
			{
				return t.IsChildOf(((Component)this).transform);
			}
			return true;
		}

		private static bool IsPlayer(Transform? t)
		{
			if ((Object)(object)t == (Object)null)
			{
				return false;
			}
			try
			{
				return (Object)(object)PlayerManager.GetPlayerFromBodyPart(t) != (Object)null;
			}
			catch
			{
				return false;
			}
		}

		private bool HasGroundNear(Vector3 pos, float refY)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: 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_0017: 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_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: 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_0098: Unknown result type (might be due to invalid IL or missing references)
			Ray val = default(Ray);
			((Ray)(ref val))..ctor(pos + Vector3.up * 1.5f, Vector3.down);
			RaycastHit[] array = Physics.RaycastAll(val, 8f, -1, (QueryTriggerInteraction)1);
			float num = WaterY();
			RaycastHit[] array2 = array;
			for (int i = 0; i < array2.Length; i++)
			{
				RaycastHit val2 = array2[i];
				if (!IsSelf(((RaycastHit)(ref val2)).transform) && !(Mathf.Abs(((RaycastHit)(ref val2)).point.y - refY) > 1.2f) && !(((RaycastHit)(ref val2)).point.y < _home.y - 0.8f) && (!(num > -999f) || !(((RaycastHit)(ref val2)).point.y < num + 0.15f)))
				{
					return true;
				}
			}
			return false;
		}

		private static float WaterY()
		{
			try
			{
				return WaterManager.WaterHeight;
			}
			catch
			{
				return -1000f;
			}
		}

		private void ApplyWalk(float dt)
		{
			//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_00e7: Unknown result type (might be due to invalid IL or missing references)
			//I