Decompiled source of Doppelganger v0.4.12

REPO.Doppelganger.dll

Decompiled 15 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using Photon.Voice;
using REPOLib.Modules;
using RepoDoppelganger.Voice;
using RepoSteamNetworking.API;
using RepoSteamNetworking.Networking;
using RepoSteamNetworking.Networking.Serialization;
using TMPro;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.Events;
using UnityEngine.Rendering;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: IgnoresAccessChecksTo("Autodesk.Fbx")]
[assembly: IgnoresAccessChecksTo("Discord.Sdk")]
[assembly: IgnoresAccessChecksTo("Domain_Reload")]
[assembly: IgnoresAccessChecksTo("Facepunch.Steamworks.Win64")]
[assembly: IgnoresAccessChecksTo("FbxBuildTestAssets")]
[assembly: IgnoresAccessChecksTo("Klattersynth")]
[assembly: IgnoresAccessChecksTo("Photon3Unity3D")]
[assembly: IgnoresAccessChecksTo("PhotonChat")]
[assembly: IgnoresAccessChecksTo("PhotonRealtime")]
[assembly: IgnoresAccessChecksTo("PhotonUnityNetworking")]
[assembly: IgnoresAccessChecksTo("PhotonUnityNetworking.Utilities")]
[assembly: IgnoresAccessChecksTo("PhotonVoice.API")]
[assembly: IgnoresAccessChecksTo("PhotonVoice")]
[assembly: IgnoresAccessChecksTo("PhotonVoice.PUN")]
[assembly: IgnoresAccessChecksTo("SingularityGroup.HotReload.Runtime.Public")]
[assembly: IgnoresAccessChecksTo("Sirenix.OdinInspector.Attributes")]
[assembly: IgnoresAccessChecksTo("Sirenix.OdinInspector.Modules.Unity.Addressables")]
[assembly: IgnoresAccessChecksTo("Sirenix.OdinInspector.Modules.UnityLocalization")]
[assembly: IgnoresAccessChecksTo("Sirenix.Serialization.Config")]
[assembly: IgnoresAccessChecksTo("Sirenix.Serialization")]
[assembly: IgnoresAccessChecksTo("Sirenix.Utilities")]
[assembly: IgnoresAccessChecksTo("Unity.Addressables")]
[assembly: IgnoresAccessChecksTo("Unity.AI.Navigation")]
[assembly: IgnoresAccessChecksTo("Unity.Burst")]
[assembly: IgnoresAccessChecksTo("Unity.Burst.Unsafe")]
[assembly: IgnoresAccessChecksTo("Unity.Collections")]
[assembly: IgnoresAccessChecksTo("Unity.Collections.LowLevel.ILSupport")]
[assembly: IgnoresAccessChecksTo("Unity.Formats.Fbx.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.InputSystem")]
[assembly: IgnoresAccessChecksTo("Unity.InputSystem.ForUI")]
[assembly: IgnoresAccessChecksTo("Unity.InternalAPIEngineBridge.013")]
[assembly: IgnoresAccessChecksTo("Unity.Localization")]
[assembly: IgnoresAccessChecksTo("Unity.Mathematics")]
[assembly: IgnoresAccessChecksTo("Unity.MemoryProfiler")]
[assembly: IgnoresAccessChecksTo("Unity.Postprocessing.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.Profiling.Core")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.ShaderLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.ShaderGraph.ShaderGraphLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.ResourceManager")]
[assembly: IgnoresAccessChecksTo("Unity.ScriptableBuildPipeline")]
[assembly: IgnoresAccessChecksTo("Unity.Splines")]
[assembly: IgnoresAccessChecksTo("Unity.TextMeshPro")]
[assembly: IgnoresAccessChecksTo("Unity.Timeline")]
[assembly: IgnoresAccessChecksTo("Unity.VisualScripting.Antlr3.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.VisualScripting.Core")]
[assembly: IgnoresAccessChecksTo("Unity.VisualScripting.Flow")]
[assembly: IgnoresAccessChecksTo("Unity.VisualScripting.State")]
[assembly: IgnoresAccessChecksTo("UnityEngine.ARModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.NVIDIAModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.UI")]
[assembly: IgnoresAccessChecksTo("websocket-sharp")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("REPO.Doppelganger")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.4.12.0")]
[assembly: AssemblyInformationalVersion("0.4.12")]
[assembly: AssemblyProduct("REPO.Doppelganger")]
[assembly: AssemblyTitle("REPO.Doppelganger")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.4.12.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace RepoDoppelganger
{
	internal static class CompatibilityFixes
	{
		private sealed class EnemyTimerOverride
		{
			internal EnemyParent Parent;

			internal float OriginalTimer;
		}

		private const string BrokenSoundPatchType = "loaforcsSoundAPI.REPO.Patches.SoundPatch";

		internal static IEnumerator RemoveBrokenSoundApiLoopPrefix(Harmony harmony)
		{
			MethodInfo playLoop = AccessTools.Method(typeof(Sound), "PlayLoop", (Type[])null, (Type[])null);
			if (playLoop == null)
			{
				yield break;
			}
			float remaining = 8f;
			while (remaining > 0f)
			{
				Type type = (from assembly in AppDomain.CurrentDomain.GetAssemblies()
					select assembly.GetType("loaforcsSoundAPI.REPO.Patches.SoundPatch", throwOnError: false)).FirstOrDefault((Type type2) => type2 != null);
				MethodInfo brokenPrefix = ((type == null) ? null : AccessTools.Method(type, "ResetAudioInfoFetched", (Type[])null, (Type[])null));
				Patches patchInfo = Harmony.GetPatchInfo((MethodBase)playLoop);
				if (brokenPrefix != null && patchInfo != null && patchInfo.Prefixes.Any((Patch patch) => patch.PatchMethod == brokenPrefix))
				{
					harmony.Unpatch((MethodBase)playLoop, brokenPrefix);
					Plugin.Log.LogWarning((object)"Removed loaforcsSoundAPI_REPO's null-unsafe Sound.PlayLoop prefix. Looping vehicle and enemy audio can now run without its repeated NullReferenceException.");
					break;
				}
				remaining -= Time.unscaledDeltaTime;
				yield return null;
			}
		}

		internal static IEnumerator InstallTimerModCompatibility(Harmony harmony)
		{
			float remaining = 8f;
			while (remaining > 0f)
			{
				Type type = (from assembly in AppDomain.CurrentDomain.GetAssemblies()
					select assembly.GetType("TimerPlugin.EnemyListUI", throwOnError: false)).FirstOrDefault((Type type2) => type2 != null);
				if (type != null)
				{
					MethodInfo methodInfo = AccessTools.Method(typeof(CompatibilityFixes), "TimerEnemyListPrefix", (Type[])null, (Type[])null);
					MethodInfo methodInfo2 = AccessTools.Method(typeof(CompatibilityFixes), "TimerEnemyListFinalizer", (Type[])null, (Type[])null);
					int num = 0;
					string[] array = new string[2] { "Fetch", "Update" };
					foreach (string text in array)
					{
						MethodInfo methodInfo3 = AccessTools.Method(type, text, (Type[])null, (Type[])null);
						if (!(methodInfo3 == null) && !(methodInfo == null) && !(methodInfo2 == null))
						{
							harmony.Patch((MethodBase)methodInfo3, new HarmonyMethod(methodInfo), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(methodInfo2), (HarmonyMethod)null);
							num++;
						}
					}
					if (num > 0)
					{
						Plugin.Log.LogInfo((object)"TimerMod compatibility enabled: its enemy panel now shows the Doppelganger head's real respawn countdown.");
					}
					break;
				}
				remaining -= Time.unscaledDeltaTime;
				yield return null;
			}
		}

		private static void TimerEnemyListPrefix(out List<EnemyTimerOverride> __state)
		{
			__state = new List<EnemyTimerOverride>();
			EnemyDirector instance = EnemyDirector.instance;
			if ((Object)(object)instance == (Object)null || instance.enemiesSpawned == null)
			{
				return;
			}
			foreach (EnemyParent item in instance.enemiesSpawned)
			{
				if (!((Object)(object)item == (Object)null) && !item.Spawned && !((Object)(object)item.Enemy == (Object)null))
				{
					DoppelgangerController component = ((Component)item.Enemy).GetComponent<DoppelgangerController>();
					if (!((Object)(object)component == (Object)null))
					{
						__state.Add(new EnemyTimerOverride
						{
							Parent = item,
							OriginalTimer = item.DespawnedTimer
						});
						item.DespawnedTimer = (DoppelgangerHeadController.TryGetRemainingRespawnSeconds(component.RuntimeId, out var remaining) ? remaining : Mathf.Min(item.DespawnedTimer, Plugin.RespawnSeconds.Value));
					}
				}
			}
		}

		private static Exception? TimerEnemyListFinalizer(Exception? __exception, List<EnemyTimerOverride>? __state)
		{
			if (__state != null)
			{
				foreach (EnemyTimerOverride item in __state)
				{
					if ((Object)(object)item.Parent != (Object)null)
					{
						item.Parent.DespawnedTimer = item.OriginalTimer;
					}
				}
			}
			return __exception;
		}

		internal static void EnsureVehicleTumble(PlayerAvatar? player)
		{
			if ((Object)(object)player == (Object)null || (Object)(object)player.tumble == (Object)null || player.tumble.isTumbling)
			{
				return;
			}
			PlayerController instance = PlayerController.instance;
			bool debugNoTumble = (Object)(object)instance != (Object)null && instance.DebugNoTumble;
			if ((Object)(object)instance != (Object)null)
			{
				instance.DebugNoTumble = false;
			}
			try
			{
				if (SemiFunc.IsMasterClientOrSingleplayer())
				{
					player.tumble.TumbleSet(true, false);
				}
				else if (player.isLocal)
				{
					player.tumble.TumbleRequest(true, false);
				}
			}
			finally
			{
				if ((Object)(object)instance != (Object)null)
				{
					instance.DebugNoTumble = debugNoTumble;
				}
			}
			if (player.isLocal && (Object)(object)PlayerController.instance != (Object)null)
			{
				PlayerController.instance.tumbleInputDisableTimer = Mathf.Max(PlayerController.instance.tumbleInputDisableTimer, 1f);
			}
		}
	}
	[HarmonyPatch(typeof(ItemVehicle), "SetSeatGrabber")]
	internal static class ItemVehicleSetSeatCompatibilityPatch
	{
		[HarmonyPostfix]
		private static void Postfix(ItemVehicle __instance, int _seatIndex, PlayerAvatar _playerAvatar)
		{
			CompatibilityFixes.EnsureVehicleTumble(_playerAvatar);
		}
	}
	[HarmonyPatch(typeof(ItemVehicle), "Update")]
	internal static class ItemVehicleUpdateCompatibilityPatch
	{
		[HarmonyPrefix]
		private static void Prefix(ItemVehicle __instance)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Invalid comparison between Unknown and I4
			if (__instance.seats == null)
			{
				return;
			}
			VehicleSeat[] seats = __instance.seats;
			foreach (VehicleSeat val in seats)
			{
				PlayerAvatar val2 = val?.seatedPlayer;
				if (!((Object)(object)val2 == (Object)null) && (!(val.grabbedTimer <= 0f) || (int)__instance.currentState == 1))
				{
					CompatibilityFixes.EnsureVehicleTumble(val2);
					if (val.reachedFirstMount && val2.isLocal && (Object)(object)val2.physGrabber != (Object)null)
					{
						val2.physGrabber.OverrideColorToGreen(0.15f);
					}
				}
			}
		}
	}
	public sealed class DoppelgangerBrain : MonoBehaviour
	{
		private enum DeliveryStage
		{
			None,
			Approach,
			Carry,
			Place
		}

		private const float VisionRange = 22f;

		private const float VisionDot = 0.574f;

		private const float GunDistance = 5.5f;

		private const float GunMaximumDistance = 20f;

		private const float MeleeDistance = 3f;

		private const float AimSettleTime = 0.45f;

		private const float ShotInterval = 1.5f;

		private const float WalkSpeed = 2.3f;

		private const float SprintSpeed = 5.2f;

		private const float PeacefulFollowDistance = 2.8f;

		private const float LostSightDuration = 10f;

		private const float HostileSearchDuration = 90f;

		private const float SabotageImpactTime = 0.48f;

		private const float SabotageAnimationTime = 1.05f;

		private const float HearingRange = 24f;

		private const float SearchPathGrace = 1.25f;

		private const float StuckRecoveryTime = 2.25f;

		private const float CautiousTraversalSpeed = 1.4f;

		private const float GapProbeMaximumDistance = 9f;

		private const float GapMaximumWidth = 6.8f;

		private const float GapApproachDistance = 0.55f;

		private const float PlayerDoubleJumpThreshold = 4.6f;

		private const float SafeWalkProbeDepth = 1.45f;

		private const float SafeWalkLookAhead = 1.35f;

		private const float SafeWalkHalfWidth = 0.2f;

		private Enemy _enemy;

		private EnemyParent _parent;

		private EnemyHealth _health;

		private DoppelgangerController _controller;

		private PlayerAvatar? _combatTarget;

		private PlayerAvatar? _inspectTarget;

		private PlayerAvatar? _peacefulTarget;

		private Vector3 _facing;

		private Vector3 _lastSeenPosition;

		private Vector3 _visibleTargetPoint;

		private Vector3 _investigatePosition;

		private Vector3 _roamPosition;

		private Vector3 _searchDestination;

		private Vector3 _deliveryNavigationPoint;

		private Vector3 _deliveryDropPoint;

		private Vector3 _humanMovePoint;

		private Vector3 _humanDestinationAnchor;

		private Vector3 _lastAcceptedSoundPosition;

		private Vector3 _lastSafeNavPosition;

		private Vector3 _stuckAnchorPosition;

		private Vector3 _stuckDestination;

		private Vector3 _lastIssuedDestination;

		private Vector3 _managedGapStart;

		private Vector3 _managedGapLanding;

		private readonly List<LevelPoint> _searchRoute = new List<LevelPoint>();

		private int _searchRouteIndex;

		private float _visionTimer;

		private float _lastSeenTimer;

		private float _inspectTimer;

		private float _investigateTimer;

		private float _roamTimer;

		private float _aimTimer;

		private float _shotCooldown;

		private float _visibilityGraceTimer;

		private float _jumpCheckTimer;

		private float _peacefulInteraction;

		private float _peacefulInteractionLimit;

		private float _knownTargetTimer;

		private float _hostileSearchTimer;

		private float _searchPointTimer;

		private float _searchScanTimer;

		private float _searchYaw;

		private float _sabotageCooldown;

		private float _sabotageTimer;

		private float _deliveryCooldown;

		private float _deliveryTimer;

		private float _humanMoveTimer;

		private float _randomJumpTimer;

		private float _mapInspectCooldown;

		private float _mapInspectTimer;

		private float _mapLookTimer;

		private float _lastAcceptedSoundTime = -100f;

		private float _searchPathGraceTimer;

		private float _searchNoPathTimer;

		private float _safeNavSampleTimer;

		private float _navRecoveryCooldown;

		private float _stuckTimer;

		private float _destinationRefreshTimer;

		private float _dangerousTraversalTimer;

		private float _managedGapCooldown;

		private float _managedDoubleJumpTimer;

		private float _managedGapSafetyTimer;

		private float _unsafePathLogCooldown;

		private bool _targetVisible;

		private bool _wasPhysicsControlled;

		private bool _gunMode;

		private bool _searching = true;

		private bool _sabotageActive;

		private bool _sabotageImpactTriggered;

		private bool _mapInspectActive;

		private bool _hasSafeNavPosition;

		private bool _lastMoveSprinting;

		private bool _dangerousTraversal;

		private bool _managedGapJumpActive;

		private bool _managedDoubleJumpPending;

		private DeliveryStage _deliveryStage;

		private ValuableObject? _deliveryValuable;

		private PhysGrabObject? _deliveryObject;

		private PhysGrabCart? _deliveryCart;

		private ExtractionPoint? _deliveryExtraction;

		private PhysGrabCart? _ambientCartTarget;

		private Vector3 _mapLookPoint;

		private int _debugSoundSerial;

		internal bool CanUseAmbientGrab
		{
			get
			{
				if (!_controller.IsAggressive && !_searching && !_sabotageActive && _deliveryStage == DeliveryStage.None && (Object)(object)_ambientCartTarget == (Object)null)
				{
					return !_mapInspectActive;
				}
				return false;
			}
		}

		internal Vector3 DebugPosition => Position;

		internal string DebugState
		{
			get
			{
				if (_controller.UnderExternalPhysicsControl)
				{
					return "Tumble / física externa";
				}
				if (_controller.IsAggressive)
				{
					if ((Object)(object)_inspectTarget != (Object)null)
					{
						return "Hostil: olhando sob obstáculo";
					}
					if (_searching)
					{
						if (!(_investigateTimer > 0f))
						{
							if (!(_searchScanTimer > 0f))
							{
								return "Hostil: vasculhando salas";
							}
							return "Hostil: escaneando sala";
						}
						return "Hostil: investigando som";
					}
					if (_targetVisible)
					{
						if (!_gunMode)
						{
							return "Hostil: perseguição / melee";
						}
						return "Hostil: mirando / atirando";
					}
					return "Hostil: última posição conhecida";
				}
				if (_sabotageActive)
				{
					return "Pacífico: sabotagem";
				}
				if (_mapInspectActive)
				{
					return "Pacífico: encenando mapa";
				}
				if (_deliveryStage != DeliveryStage.None)
				{
					return $"Pacífico: entrega ({_deliveryStage})";
				}
				if ((Object)(object)_ambientCartTarget != (Object)null)
				{
					return "Pacífico: aproximando do KART";
				}
				if (_searching)
				{
					if (!(_investigateTimer > 0f))
					{
						if (!(_searchScanTimer > 0f))
						{
							return "Procurando: vasculhando salas";
						}
						return "Procurando: escaneando sala";
					}
					return "Procurando: investigando som";
				}
				if (IsValidPlayer(_peacefulTarget))
				{
					return "Pacífico: seguindo jogador";
				}
				return "Pacífico: livre";
			}
		}

		internal string DebugObjective
		{
			get
			{
				//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
				//IL_0166: Unknown result type (might be due to invalid IL or missing references)
				//IL_0150: Unknown result type (might be due to invalid IL or missing references)
				if (_deliveryStage != DeliveryStage.None)
				{
					string arg = (((Object)(object)_deliveryValuable != (Object)null) ? ((Object)_deliveryValuable).name : "valuable perdido");
					string arg2 = (((Object)(object)_deliveryExtraction != (Object)null) ? "extração" : (((Object)(object)_deliveryCart != (Object)null) ? "KART" : "destino perdido"));
					return $"{_deliveryStage}: {arg} -> {arg2}";
				}
				if (_mapInspectActive)
				{
					return "Olhar o mapa e arredores";
				}
				if (_sabotageActive)
				{
					if (!_sabotageImpactTriggered)
					{
						return "Bater no chão para atrair monstros";
					}
					return "Sabotagem disparada";
				}
				if ((Object)(object)_ambientCartTarget != (Object)null)
				{
					return "Alcançar KART " + ((Object)_ambientCartTarget).name;
				}
				if (_investigateTimer > 0f)
				{
					return "Checar som em " + FormatVector(_investigatePosition);
				}
				if (_controller.IsAggressive && IsValidPlayer(_combatTarget))
				{
					return "Atacar " + _combatTarget.playerName;
				}
				if (IsValidPlayer(_peacefulTarget))
				{
					return "Seguir " + _peacefulTarget.playerName;
				}
				if (_searching)
				{
					if (!(_searchScanTimer > 0f))
					{
						return "Ir para sala em " + FormatVector(_searchDestination);
					}
					return "Escanear " + FormatVector(_searchDestination);
				}
				return "Nenhum";
			}
		}

		internal float DebugHostilityPercent
		{
			get
			{
				if (!_controller.IsAggressive)
				{
					return Mathf.Clamp01(_peacefulInteraction / Mathf.Max(0.01f, _peacefulInteractionLimit)) * 100f;
				}
				return 100f;
			}
		}

		internal float DebugHostilityValue => _peacefulInteraction;

		internal float DebugHostilityLimit => _peacefulInteractionLimit;

		internal float DebugLastSeenSeconds => _lastSeenTimer;

		internal float DebugKnownTargetSeconds => _knownTargetTimer;

		internal float DebugHostileSearchSeconds => _hostileSearchTimer;

		internal float DebugInvestigateSeconds => _investigateTimer;

		internal float DebugSabotageCooldown => _sabotageCooldown;

		internal float DebugDeliveryCooldown => _deliveryCooldown;

		internal float DebugMapCooldown => _mapInspectCooldown;

		internal bool DebugTargetVisible => _targetVisible;

		internal int DebugSoundSerial => _debugSoundSerial;

		private Vector3 Position
		{
			get
			{
				//IL_0026: 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)
				if (!_enemy.HasRigidbody || !((Object)(object)_enemy.Rigidbody != (Object)null))
				{
					return ((Component)this).transform.position;
				}
				return ((Component)_enemy.Rigidbody).transform.position;
			}
		}

		private static string FormatVector(Vector3 value)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			return $"{value.x:0.0}, {value.y:0.0}, {value.z:0.0}";
		}

		private void Awake()
		{
			//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)
			_enemy = ((Component)this).GetComponent<Enemy>();
			_parent = ((Component)this).GetComponentInParent<EnemyParent>();
			_health = ((Component)this).GetComponent<EnemyHealth>();
			_controller = ((Component)this).GetComponent<DoppelgangerController>();
			_facing = ((Component)this).transform.forward;
			_roamTimer = Random.Range(1.5f, 3f);
			_peacefulInteractionLimit = Random.Range(24f, 40f);
			_sabotageCooldown = Random.Range(180f, 240f);
			_deliveryCooldown = Random.Range(45f, 100f);
			_randomJumpTimer = Random.Range(4.5f, 10f);
			_mapInspectCooldown = Random.Range(30f, 65f);
		}

		private void Start()
		{
			//IL_0052: 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_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Expected O, but got Unknown
			if (_enemy.HasNavMeshAgent && (Object)(object)_enemy.NavMeshAgent != (Object)null)
			{
				_enemy.NavMeshAgent.Agent.stoppingDistance = 0.3f;
				_enemy.NavMeshAgent.Agent.autoBraking = true;
				_stuckAnchorPosition = Position;
				RefreshSafeNavPosition(force: true);
			}
			if (_enemy.HasJump && (Object)(object)_enemy.Jump != (Object)null)
			{
				_enemy.Jump.gapJump = false;
				_enemy.Jump.warpAgentOnLand = true;
				_enemy.Jump.surfaceJump = true;
				_enemy.Jump.stuckJump = false;
				_enemy.Jump.surfaceJumpDelay = 0f;
				_enemy.Jump.surfaceLandDelay = 0f;
				_enemy.Jump.stuckJumpDelay = 0f;
				_enemy.Jump.stuckLandDelay = 0f;
				_enemy.Jump.gapJumpDelay = 0f;
				_enemy.Jump.gapLandDelay = 0f;
			}
			if (_enemy.HasStateInvestigate && (Object)(object)_enemy.StateInvestigate != (Object)null && _enemy.StateInvestigate.onInvestigateTriggered != null)
			{
				_enemy.StateInvestigate.onInvestigateTriggered.AddListener(new UnityAction(OnInvestigate));
			}
		}

		private void Update()
		{
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
			if (!SemiFunc.IsMasterClientOrSingleplayer() || !_parent.Spawned || _health.healthCurrent <= 0 || _health.dead)
			{
				return;
			}
			if (!_controller.IsAggressive && _controller.IsBeingGrabbed)
			{
				_peacefulInteraction += Time.deltaTime * 4f;
				TryTriggerInteractionAggression();
			}
			_managedGapCooldown = Mathf.Max(0f, _managedGapCooldown - Time.deltaTime);
			_dangerousTraversalTimer = Mathf.Max(0f, _dangerousTraversalTimer - Time.deltaTime);
			_unsafePathLogCooldown = Mathf.Max(0f, _unsafePathLogCooldown - Time.deltaTime);
			UpdateManagedGapJump();
			if (_controller.UnderExternalPhysicsControl)
			{
				CancelMapInspection();
				if (!_wasPhysicsControlled)
				{
					StopMoving();
					_wasPhysicsControlled = true;
				}
				_gunMode = false;
				_aimTimer = 0f;
				_controller.SetCombatPoseHost(sprinting: false, crouching: false, gunDrawn: false, Position);
				return;
			}
			if (_wasPhysicsControlled)
			{
				_wasPhysicsControlled = false;
				if (_enemy.HasNavMeshAgent && (Object)(object)_enemy.NavMeshAgent != (Object)null)
				{
					RecoverAgentToNavMesh("fim do Tumble/física externa", force: true);
				}
				_visionTimer = 0f;
			}
			_navRecoveryCooldown = Mathf.Max(0f, _navRecoveryCooldown - Time.deltaTime);
			_destinationRefreshTimer = Mathf.Max(0f, _destinationRefreshTimer - Time.deltaTime);
			_searchPathGraceTimer = Mathf.Max(0f, _searchPathGraceTimer - Time.deltaTime);
			RefreshSafeNavPosition(force: false);
			if (!EnsureAgentOnNavMesh())
			{
				_gunMode = false;
				_aimTimer = 0f;
				_controller.SetCombatPoseHost(sprinting: false, crouching: false, gunDrawn: false, Position);
				return;
			}
			_shotCooldown = Mathf.Max(0f, _shotCooldown - Time.deltaTime);
			_visibilityGraceTimer = Mathf.Max(0f, _visibilityGraceTimer - Time.deltaTime);
			_investigateTimer = Mathf.Max(0f, _investigateTimer - Time.deltaTime);
			_jumpCheckTimer = Mathf.Max(0f, _jumpCheckTimer - Time.deltaTime);
			if (_deliveryStage != DeliveryStage.None)
			{
				DeliveryUpdate();
				return;
			}
			if (_sabotageActive)
			{
				SabotageUpdate();
				return;
			}
			if (_controller.IsAggressive)
			{
				AggressiveUpdate();
				return;
			}
			_sabotageCooldown = Mathf.Max(0f, _sabotageCooldown - Time.deltaTime);
			_deliveryCooldown = Mathf.Max(0f, _deliveryCooldown - Time.deltaTime);
			_mapInspectCooldown = Mathf.Max(0f, _mapInspectCooldown - Time.deltaTime);
			if (_mapInspectActive)
			{
				MapInspectionUpdate();
			}
			else if (_mapInspectCooldown <= 0f && !_controller.HasGrabTarget)
			{
				StartMapInspection();
			}
			else if (_searching)
			{
				SearchUpdate(hostile: false);
			}
			else
			{
				PeacefulUpdate();
			}
		}

		private void AggressiveUpdate()
		{
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//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_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			_lastSeenTimer = Mathf.Max(0f, _lastSeenTimer - Time.deltaTime);
			_visionTimer -= Time.deltaTime;
			if (_visionTimer <= 0f)
			{
				_visionTimer = 0.08f;
				ScanVision();
			}
			if (_searching)
			{
				SearchUpdate(hostile: true);
				return;
			}
			if ((Object)(object)_inspectTarget != (Object)null)
			{
				_gunMode = false;
				InspectLowTarget();
				return;
			}
			if (_targetVisible && IsValidPlayer(_combatTarget))
			{
				_lastSeenPosition = GetTargetPoint(_combatTarget);
				_lastSeenTimer = 10f;
				_searching = false;
				EngageVisibleTarget(_combatTarget);
				return;
			}
			_aimTimer = 0f;
			_gunMode = false;
			if (IsValidPlayer(_combatTarget) && _lastSeenTimer > 0f)
			{
				if (HorizontalDistance(Position, _lastSeenPosition) > 1.1f)
				{
					Face(_lastSeenPosition);
					MoveTo(_lastSeenPosition, 5.2f, sprint: true);
					TryJump(_lastSeenPosition);
					_controller.SetCombatPoseHost(_lastMoveSprinting, crouching: false, gunDrawn: false, _lastSeenPosition);
				}
				else
				{
					StopMoving();
					_searchYaw += Time.deltaTime * 240f;
					Vector3 val = Position + Quaternion.Euler(0f, _searchYaw, 0f) * Vector3.forward * 4f + Vector3.up * 0.7f;
					Face(val);
					_controller.SetCombatPoseHost(sprinting: false, crouching: false, gunDrawn: false, val);
				}
			}
			else
			{
				_combatTarget = null;
				if (!_searching)
				{
					EnterSearch(resetHostility: true);
				}
				SearchUpdate(hostile: true);
			}
		}

		internal void ResetPeacefulBehaviourHost()
		{
			if (SemiFunc.IsMasterClientOrSingleplayer())
			{
				_combatTarget = null;
				_inspectTarget = null;
				_peacefulTarget = null;
				_targetVisible = false;
				_lastSeenTimer = 0f;
				_aimTimer = 0f;
				_gunMode = false;
				_peacefulInteraction = 0f;
				_peacefulInteractionLimit = Random.Range(24f, 40f);
				_knownTargetTimer = 0f;
				_hostileSearchTimer = 0f;
				_sabotageActive = false;
				CancelMapInspection();
				CancelAmbientCartApproach();
				CancelDelivery();
				EnterSearch(resetHostility: false);
			}
		}

		internal void BeginAggressionHost()
		{
			//IL_0096: 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_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			if (!SemiFunc.IsMasterClientOrSingleplayer())
			{
				return;
			}
			CancelMapInspection();
			CancelAmbientCartApproach();
			CancelDelivery();
			_sabotageActive = false;
			_combatTarget = (IsValidPlayer(_peacefulTarget) ? _peacefulTarget : null);
			_peacefulTarget = null;
			_controller.SetPeacefulFollowTargetHost(null);
			_visionTimer = 0f;
			_hostileSearchTimer = 90f;
			if (IsValidPlayer(_combatTarget))
			{
				if (TryGetVisiblePoint(_combatTarget, lowEye: false, out var visiblePoint) || TryGetVisiblePoint(_combatTarget, lowEye: true, out visiblePoint))
				{
					_visibleTargetPoint = visiblePoint;
					_targetVisible = true;
					_visibilityGraceTimer = 0.5f;
					_lastSeenPosition = visiblePoint;
					_lastSeenTimer = 10f;
					_searching = false;
				}
				else
				{
					_combatTarget = null;
					EnterSearch(resetHostility: true);
				}
			}
			else
			{
				EnterSearch(resetHostility: true);
			}
		}

		private void PeacefulUpdate()
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: 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_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			if (AmbientCartApproachUpdate())
			{
				return;
			}
			if (!IsValidPlayer(_peacefulTarget))
			{
				EnterSearch(resetHostility: false);
				return;
			}
			PlayerAvatar peacefulTarget = _peacefulTarget;
			Vector3 visiblePoint = Vector3.zero;
			bool flag = InsideFieldOfView(peacefulTarget) && (TryGetVisiblePoint(peacefulTarget, lowEye: false, out visiblePoint) || TryGetVisiblePoint(peacefulTarget, lowEye: true, out visiblePoint));
			if (flag)
			{
				_lastSeenPosition = GetPlayerPhysicalPosition(peacefulTarget);
				_visibleTargetPoint = visiblePoint;
				_knownTargetTimer = 10f;
			}
			else
			{
				_knownTargetTimer = Mathf.Max(0f, _knownTargetTimer - Time.deltaTime);
				if (_knownTargetTimer <= 0f)
				{
					EnterSearch(resetHostility: false);
					return;
				}
			}
			Vector3 val = (flag ? GetPlayerPhysicalPosition(peacefulTarget) : _lastSeenPosition);
			Vector3 val2 = (flag ? _visibleTargetPoint : (_lastSeenPosition + Vector3.up * 0.6f));
			float num = HorizontalDistance(Position, val);
			Face(val2);
			if (num > 3.6f)
			{
				bool flag2 = num > 10f;
				MoveTo(val, flag2 ? 5.2f : 2.3f, flag2);
				TryJump(val);
				_controller.SetCombatPoseHost(_lastMoveSprinting, crouching: false, gunDrawn: false, val2);
			}
			else
			{
				StopMoving();
				_controller.SetCombatPoseHost(sprinting: false, peacefulTarget.isCrouching || peacefulTarget.isCrawling, gunDrawn: false, val2);
			}
			if (num <= 4.2f && flag)
			{
				float num2 = 1f;
				if ((Object)(object)peacefulTarget.voiceChat != (Object)null && peacefulTarget.voiceChat.isTalking)
				{
					num2 += 0.75f;
				}
				_peacefulInteraction += Time.deltaTime * num2;
				TryTriggerInteractionAggression();
			}
			else
			{
				_peacefulInteraction = Mathf.Max(0f, _peacefulInteraction - Time.deltaTime * 0.15f);
			}
			if (_sabotageCooldown <= 0f)
			{
				StartSabotage(peacefulTarget);
			}
		}

		private void StartMapInspection()
		{
			if (_controller.IsAggressive || _controller.HasGrabTarget)
			{
				_mapInspectCooldown = Random.Range(15f, 30f);
				return;
			}
			_mapInspectActive = true;
			_mapInspectTimer = Random.Range(5.5f, 8f);
			_mapLookTimer = 0f;
			_mapInspectCooldown = Random.Range(55f, 105f);
			StopMoving();
			_controller.SetMapInspectHost(active: true);
			DoppelgangerDebugOverlay.Record(_controller, "MAPA", "abriu o mapa para encenar e observar os arredores");
			Plugin.Log.LogDebug((object)"Doppelganger stopped to fake checking the player map.");
		}

		private void MapInspectionUpdate()
		{
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: 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_010a: 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_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: 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_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: 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_00c8: 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)
			if (_controller.IsAggressive || _controller.UnderExternalPhysicsControl)
			{
				CancelMapInspection();
				return;
			}
			StopMoving();
			_mapInspectTimer -= Time.deltaTime;
			_mapLookTimer -= Time.deltaTime;
			if (_mapLookTimer <= 0f)
			{
				_mapLookTimer = Random.Range(0.75f, 1.45f);
				if (Random.value < 0.58f)
				{
					Vector3 val = ((((Vector3)(ref _facing)).sqrMagnitude > 0.01f) ? ((Vector3)(ref _facing)).normalized : ((Component)this).transform.forward);
					_mapLookPoint = Position + val * 1.15f + Vector3.up * 0.22f;
				}
				else
				{
					Vector3 val2 = Quaternion.AngleAxis(Random.Range(-105f, 105f), Vector3.up) * ((((Vector3)(ref _facing)).sqrMagnitude > 0.01f) ? ((Vector3)(ref _facing)).normalized : ((Component)this).transform.forward);
					_mapLookPoint = Position + val2 * 4f + Vector3.up * 0.8f;
				}
			}
			Face(_mapLookPoint);
			_controller.SetCombatPoseHost(sprinting: false, crouching: false, gunDrawn: false, _mapLookPoint);
			if (_mapInspectTimer <= 0f)
			{
				CancelMapInspection();
			}
		}

		private void CancelMapInspection()
		{
			if (_mapInspectActive)
			{
				_mapInspectActive = false;
				if ((Object)(object)_controller != (Object)null)
				{
					_controller.SetMapInspectHost(active: false);
					DoppelgangerDebugOverlay.Record(_controller, "MAPA", "fechou o mapa");
				}
			}
		}

		private void TryTriggerInteractionAggression()
		{
			if (!_controller.IsAggressive && _peacefulInteraction >= _peacefulInteractionLimit)
			{
				_controller.BecomeAggressiveHost("prolonged interaction with a player");
			}
		}

		private void EnterSearch(bool resetHostility)
		{
			//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)
			bool searching = _searching;
			CancelAmbientCartApproach();
			_searching = true;
			_peacefulTarget = null;
			_combatTarget = null;
			_inspectTarget = null;
			_targetVisible = false;
			_knownTargetTimer = 0f;
			_lastSeenTimer = 0f;
			_aimTimer = 0f;
			_gunMode = false;
			_controller.SetPeacefulFollowTargetHost(null);
			if (resetHostility && _controller.IsAggressive && !searching)
			{
				_hostileSearchTimer = 90f;
				DoppelgangerDebugOverlay.Record(_controller, "HOSTILIDADE", $"perdeu o alvo; busca hostil resetada para {90f:0}s");
			}
			if (!searching || _searchRoute.Count == 0 || _searchDestination == Vector3.zero)
			{
				BuildSearchRoute();
				PickNextSearchPoint();
			}
		}

		internal void RequestAmbientCartApproachHost(PhysGrabCart cart)
		{
			if (SemiFunc.IsMasterClientOrSingleplayer() && !((Object)(object)cart == (Object)null) && CanUseAmbientGrab && CartCanBeHandled(cart))
			{
				_ambientCartTarget = cart;
			}
		}

		private bool AmbientCartApproachUpdate()
		{
			//IL_005e: 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_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: 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_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: 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_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			PhysGrabCart ambientCartTarget = _ambientCartTarget;
			if ((Object)(object)ambientCartTarget == (Object)null)
			{
				return false;
			}
			if (_controller.IsAggressive || !CartCanBeHandled(ambientCartTarget))
			{
				CancelAmbientCartApproach();
				return false;
			}
			Transform val = (((Object)(object)ambientCartTarget.handlePoint != (Object)null) ? ambientCartTarget.handlePoint : ambientCartTarget.cartGrabPoint);
			if ((Object)(object)val == (Object)null)
			{
				CancelAmbientCartApproach();
				return false;
			}
			Vector3 val2 = val.position - ((Component)ambientCartTarget).transform.position;
			val2.y = 0f;
			if (((Vector3)(ref val2)).sqrMagnitude < 0.01f)
			{
				val2 = -((Component)ambientCartTarget).transform.forward;
				val2.y = 0f;
			}
			((Vector3)(ref val2)).Normalize();
			Vector3 val3 = val.position + val2 * 0.72f;
			NavMeshHit val4 = default(NavMeshHit);
			if (NavMesh.SamplePosition(val3, ref val4, 1.5f, -1))
			{
				val3 = ((NavMeshHit)(ref val4)).position;
			}
			Vector3 val5 = ((Component)ambientCartTarget).transform.position + Vector3.up * 0.45f;
			if (HorizontalDistance(Position, val3) > 0.7f)
			{
				Face(val5);
				MoveTo(val3, 2.3f, sprint: false);
				TryJump(val3);
				_controller.SetCombatPoseHost(sprinting: false, crouching: false, gunDrawn: false, val5);
				return true;
			}
			StopMoving();
			Face(val5);
			_controller.SetCombatPoseHost(sprinting: false, crouching: false, gunDrawn: false, val5);
			_ambientCartTarget = null;
			_controller.BeginAmbientCartGrabHost(ambientCartTarget);
			return true;
		}

		private static bool CartCanBeHandled(PhysGrabCart cart)
		{
			PhysGrabObject val = (((Object)(object)cart != (Object)null) ? cart.physGrabObject : null);
			if ((Object)(object)val != (Object)null && (Object)(object)val.rb != (Object)null && !val.grabbed && !val.grabbedLocal)
			{
				return val.playerGrabbing.Count == 0;
			}
			return false;
		}

		private void CancelAmbientCartApproach()
		{
			_ambientCartTarget = null;
		}

		private void SearchUpdate(bool hostile)
		{
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: 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_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Unknown result type (might be due to invalid IL or missing references)
			//IL_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_0244: 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_02dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0306: Unknown result type (might be due to invalid IL or missing references)
			//IL_030b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0310: Unknown result type (might be due to invalid IL or missing references)
			//IL_031a: 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_0324: Unknown result type (might be due to invalid IL or missing references)
			//IL_0326: 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_0268: Unknown result type (might be due to invalid IL or missing references)
			//IL_0274: Unknown result type (might be due to invalid IL or missing references)
			//IL_0286: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a1: Unknown result type (might be due to invalid IL or missing references)
			_visionTimer -= Time.deltaTime;
			if (_visionTimer <= 0f)
			{
				_visionTimer = 0.08f;
				ScanVision();
			}
			if ((Object)(object)_inspectTarget != (Object)null)
			{
				InspectLowTarget();
				if (!hostile && _targetVisible && IsValidPlayer(_combatTarget))
				{
					BeginPeacefulFollow(_combatTarget, _visibleTargetPoint);
				}
				return;
			}
			if (_targetVisible && IsValidPlayer(_combatTarget))
			{
				if (hostile)
				{
					_searching = false;
					_lastSeenPosition = _visibleTargetPoint;
					_lastSeenTimer = 10f;
					EngageVisibleTarget(_combatTarget);
				}
				else
				{
					BeginPeacefulFollow(_combatTarget, _visibleTargetPoint);
				}
				return;
			}
			if (hostile)
			{
				_hostileSearchTimer = Mathf.Max(0f, _hostileSearchTimer - Time.deltaTime);
				if (_hostileSearchTimer <= 0f)
				{
					_controller.BecomePeacefulHost("its hostile search expired");
					return;
				}
			}
			else if (_deliveryCooldown <= 0f)
			{
				_deliveryCooldown = Random.Range(70f, 130f);
				if (Random.value <= 0.45f && TryStartDeliveryScene())
				{
					return;
				}
			}
			if (_investigateTimer > 0f)
			{
				Face(_investigatePosition);
				MoveTo(_investigatePosition, 5.2f, sprint: true);
				TryJump(_investigatePosition);
				_controller.SetCombatPoseHost(_lastMoveSprinting, crouching: false, gunDrawn: false, _investigatePosition);
				if (HorizontalDistance(Position, _investigatePosition) <= 1.3f)
				{
					_investigateTimer = 0f;
				}
				return;
			}
			bool num = HorizontalDistance(Position, _searchDestination) > 1.6f;
			bool flag = HasUsableNavigationPath();
			if (num && _searchPathGraceTimer <= 0f && !flag)
			{
				_searchNoPathTimer += Time.deltaTime;
			}
			else
			{
				_searchNoPathTimer = 0f;
			}
			if (_searchDestination == Vector3.zero || _searchPointTimer <= 0f || _searchNoPathTimer >= 1.1f)
			{
				PickNextSearchPoint();
			}
			_searchPointTimer -= Time.deltaTime;
			if (HorizontalDistance(Position, _searchDestination) > 1.35f)
			{
				_searchScanTimer = 0f;
				Face(_searchDestination);
				MoveTo(_searchDestination, 5.2f, sprint: true);
				TryJump(_searchDestination);
				_controller.SetCombatPoseHost(_lastMoveSprinting, crouching: false, gunDrawn: false, _searchDestination);
				return;
			}
			StopMoving();
			_searchScanTimer += Time.deltaTime;
			_searchYaw += Time.deltaTime * 210f;
			Vector3 val = Position + Quaternion.Euler(0f, _searchYaw, 0f) * Vector3.forward * 4f + Vector3.up * 0.7f;
			Face(val);
			_controller.SetCombatPoseHost(sprinting: false, crouching: false, gunDrawn: false, val);
			if (_searchScanTimer >= 1.7f)
			{
				PickNextSearchPoint();
			}
		}

		private void BeginPeacefulFollow(PlayerAvatar target, Vector3 visiblePoint)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: 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)
			_searching = false;
			_peacefulTarget = target;
			_combatTarget = null;
			_inspectTarget = null;
			_targetVisible = false;
			_lastSeenPosition = GetPlayerPhysicalPosition(target);
			_visibleTargetPoint = visiblePoint;
			_knownTargetTimer = 10f;
			_controller.SetPeacefulFollowTargetHost(target);
			DoppelgangerDebugOverlay.Record(_controller, "VISÃO", "encontrou " + target.playerName + " e começou a seguir");
			Plugin.Log.LogDebug((object)("Doppelganger found \"" + target.playerName + "\" naturally and began following."));
		}

		private void BuildSearchRoute()
		{
			_searchRoute.Clear();
			_searchRouteIndex = 0;
			if ((Object)(object)LevelGenerator.Instance == (Object)null)
			{
				return;
			}
			IEnumerable<LevelPoint> source = from point in LevelGenerator.Instance.LevelPathPoints
				where (Object)(object)point != (Object)null && (Object)(object)point.Room != (Object)null && !point.Room.Truck
				group point by point.Room into @group
				select @group.OrderByDescending((LevelPoint point) => (point.ConnectedPoints != null) ? point.ConnectedPoints.Count : 0).First();
			_searchRoute.AddRange(source.OrderBy((LevelPoint _) => Random.value));
		}

		private void PickNextSearchPoint()
		{
			//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_005d: 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_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			if (_searchRoute.Count == 0 || _searchRouteIndex >= _searchRoute.Count)
			{
				BuildSearchRoute();
			}
			NavMeshHit val2 = default(NavMeshHit);
			while (_searchRouteIndex < _searchRoute.Count)
			{
				LevelPoint val = _searchRoute[_searchRouteIndex++];
				if ((Object)(object)val != (Object)null && NavMesh.SamplePosition(((Component)val).transform.position, ref val2, 4f, -1) && TryResolveReachableDestination(((NavMeshHit)(ref val2)).position, 0.35f, out var reachable))
				{
					_searchDestination = reachable;
					_searchPointTimer = 18f;
					_searchScanTimer = 0f;
					_searchNoPathTimer = 0f;
					_searchPathGraceTimer = 1.25f;
					DoppelgangerDebugOverlay.Record(_controller, "PROCURA", "nova sala/rota: " + FormatVector(_searchDestination));
					return;
				}
			}
			_searchDestination = Position;
			_searchPointTimer = 2f;
		}

		private void StartSabotage(PlayerAvatar target)
		{
			if (!IsValidPlayer(target) || _controller.IsAggressive)
			{
				_sabotageCooldown = Random.Range(30f, 60f);
				return;
			}
			_sabotageActive = true;
			_sabotageImpactTriggered = false;
			_sabotageTimer = 1.05f;
			_sabotageCooldown = Random.Range(180f, 240f);
			_controller.PlaySabotageVisualHost();
			StopMoving();
			DoppelgangerDebugOverlay.Record(_controller, "SABOTAGEM", "iniciou a encenação de queda");
			Plugin.Log.LogDebug((object)"Doppelganger began a peaceful sabotage performance.");
		}

		private void SabotageUpdate()
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: 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_003a: 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_00b8: 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)
			if (_controller.IsAggressive)
			{
				_sabotageActive = false;
				return;
			}
			StopMoving();
			_controller.SetCombatPoseHost(sprinting: false, crouching: false, gunDrawn: false, Position + _facing * 2f);
			_sabotageTimer -= Time.deltaTime;
			if (!_sabotageImpactTriggered && _sabotageTimer <= 0.56999993f)
			{
				_sabotageImpactTriggered = true;
				if (IsValidPlayer(_peacefulTarget) && (Object)(object)EnemyDirector.instance != (Object)null)
				{
					Vector3 playerPhysicalPosition = GetPlayerPhysicalPosition(_peacefulTarget);
					AttractAllEnemies(_peacefulTarget, playerPhysicalPosition);
					DoppelgangerDebugOverlay.Record(_controller, "SABOTAGEM", "impacto: monstros atraídos para " + FormatVector(playerPhysicalPosition));
					Plugin.Log.LogInfo((object)$"Doppelganger sabotage attracted enemies to {playerPhysicalPosition}.");
				}
			}
			if (_sabotageTimer <= 0f)
			{
				_sabotageActive = false;
			}
		}

		private void AttractAllEnemies(PlayerAvatar target, Vector3 lurePosition)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			EnemyDirector.instance.SetInvestigate(lurePosition, float.MaxValue, false);
			EnemyParent[] array = Object.FindObjectsOfType<EnemyParent>();
			foreach (EnemyParent val in array)
			{
				if ((Object)(object)val == (Object)null || (Object)(object)val == (Object)(object)_parent || !val.Spawned || (Object)(object)val.Enemy == (Object)null)
				{
					continue;
				}
				Enemy enemy = val.Enemy;
				if (!enemy.HasStateInvestigate || !((Object)(object)enemy.StateInvestigate != (Object)null))
				{
					if (enemy.HasVision)
					{
						enemy.SetChaseTarget(target);
					}
					else if (enemy.HasNavMeshAgent && (Object)(object)enemy.NavMeshAgent != (Object)null)
					{
						enemy.NavMeshAgent.SetDestination(lurePosition);
					}
				}
			}
		}

		private bool TryStartDeliveryScene()
		{
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			if (_controller.IsAggressive || !_searching)
			{
				return false;
			}
			_deliveryExtraction = (((Object)(object)RoundDirector.instance != (Object)null && RoundDirector.instance.extractionPointActive) ? RoundDirector.instance.extractionPointCurrent : null);
			_deliveryCart = null;
			if ((Object)(object)_deliveryExtraction == (Object)null)
			{
				_deliveryCart = (from cart in Object.FindObjectsOfType<PhysGrabCart>()
					where (Object)(object)cart != (Object)null && (Object)(object)cart.inCart != (Object)null && (Object)(object)cart.physGrabObject != (Object)null && (Object)(object)cart.physGrabObject.rb != (Object)null
					orderby HorizontalDistance(Position, ((Component)cart).transform.position)
					select cart).FirstOrDefault();
			}
			if ((Object)(object)_deliveryExtraction == (Object)null && (Object)(object)_deliveryCart == (Object)null)
			{
				return false;
			}
			List<ValuableObject> list = (from valuable in Object.FindObjectsOfType<ValuableObject>().Where(delegate(ValuableObject valuable)
				{
					if ((Object)(object)valuable == (Object)null || !((Component)valuable).gameObject.activeInHierarchy)
					{
						return false;
					}
					PhysGrabObject component = ((Component)valuable).GetComponent<PhysGrabObject>();
					if ((Object)(object)component == (Object)null || (Object)(object)component.rb == (Object)null || component.rb.isKinematic || component.grabbed || component.grabbedLocal || component.playerGrabbing.Count > 0 || ((Object)(object)component.impactDetector != (Object)null && component.impactDetector.inCart) || (Object)(object)((Component)component).GetComponentInParent<EnemyRigidbody>() != (Object)null)
					{
						return false;
					}
					RoomVolumeCheck component2 = ((Component)valuable).GetComponent<RoomVolumeCheck>();
					return (Object)(object)component2 == (Object)null || (!component2.inExtractionPoint && !component2.inTruck);
				})
				orderby HorizontalDistance(Position, ((Component)valuable).transform.position)
				select valuable).Take(12).ToList();
			if (list.Count == 0)
			{
				return false;
			}
			_deliveryValuable = list[Random.Range(0, list.Count)];
			_deliveryObject = ((Component)_deliveryValuable).GetComponent<PhysGrabObject>();
			Vector3 val = ((!((Object)(object)_deliveryExtraction != (Object)null)) ? _deliveryCart.inCart.position : (((Object)(object)_deliveryExtraction.extractionArea != (Object)null) ? _deliveryExtraction.extractionArea.transform.position : ((Component)_deliveryExtraction).transform.position));
			_deliveryDropPoint = val + Vector3.up * 0.25f;
			NavMeshHit val2 = default(NavMeshHit);
			if (!NavMesh.SamplePosition(val, ref val2, 5f, -1))
			{
				_deliveryValuable = null;
				_deliveryObject = null;
				_deliveryCart = null;
				_deliveryExtraction = null;
				return false;
			}
			_deliveryNavigationPoint = ((NavMeshHit)(ref val2)).position;
			_deliveryStage = DeliveryStage.Approach;
			_deliveryTimer = 30f;
			DoppelgangerDebugOverlay.Record(_controller, "DELIVERY", "escolheu " + ((Object)_deliveryValuable).name + " para levar até " + (((Object)(object)_deliveryExtraction != (Object)null) ? "a extração" : "um KART"));
			Plugin.Log.LogInfo((object)("Doppelganger staged an innocent delivery of \"" + ((Object)_deliveryValuable).name + "\"."));
			return true;
		}

		private void DeliveryUpdate()
		{
			//IL_00ad: 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)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: 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_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_0218: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			if (_controller.IsAggressive || (Object)(object)_deliveryObject == (Object)null || (Object)(object)_deliveryObject.rb == (Object)null || (Object)(object)_deliveryValuable == (Object)null)
			{
				CancelDelivery();
				return;
			}
			_deliveryTimer -= Time.deltaTime;
			if (_deliveryTimer <= 0f)
			{
				if (_deliveryStage == DeliveryStage.Place)
				{
					_controller.EndDirectedGrabHost();
					FinishDelivery();
				}
				else
				{
					CancelDelivery();
					EnterSearch(resetHostility: false);
				}
				return;
			}
			switch (_deliveryStage)
			{
			case DeliveryStage.Approach:
			{
				Vector3 centerPoint = _deliveryObject.centerPoint;
				Face(centerPoint);
				if (HorizontalDistance(Position, centerPoint) > 1.8f)
				{
					MoveTo(centerPoint, 2.3f, sprint: false);
					_controller.SetCombatPoseHost(sprinting: false, crouching: false, gunDrawn: false, centerPoint);
					break;
				}
				StopMoving();
				if (!_controller.BeginDirectedGrabHost(_deliveryObject, 90f))
				{
					CancelDelivery();
					EnterSearch(resetHostility: false);
				}
				else
				{
					_deliveryStage = DeliveryStage.Carry;
					_deliveryTimer = 75f;
				}
				break;
			}
			case DeliveryStage.Carry:
				if ((Object)(object)_controller.CurrentGrabTarget != (Object)(object)_deliveryObject)
				{
					CancelDelivery();
					EnterSearch(resetHostility: false);
					break;
				}
				_controller.ClearDirectedGrabPointHost();
				Face(_deliveryNavigationPoint);
				if (HorizontalDistance(Position, _deliveryNavigationPoint) > 1.45f)
				{
					MoveTo(_deliveryNavigationPoint, 1.65f, sprint: false);
					_controller.SetCombatPoseHost(sprinting: false, crouching: false, gunDrawn: false, _deliveryNavigationPoint);
					break;
				}
				StopMoving();
				_controller.SetDirectedGrabPointHost(_deliveryDropPoint);
				_deliveryStage = DeliveryStage.Place;
				_deliveryTimer = 1.35f;
				break;
			case DeliveryStage.Place:
				StopMoving();
				_controller.SetDirectedGrabPointHost(_deliveryDropPoint);
				_controller.SetCombatPoseHost(sprinting: false, crouching: false, gunDrawn: false, _deliveryDropPoint);
				if (_deliveryTimer <= 0f || Vector3.Distance(_deliveryObject.rb.worldCenterOfMass, _deliveryDropPoint) <= 0.45f)
				{
					_controller.EndDirectedGrabHost();
					FinishDelivery();
				}
				break;
			}
		}

		private void FinishDelivery()
		{
			DoppelgangerDebugOverlay.Record(_controller, "DELIVERY", "entrega encenada concluída");
			Plugin.Log.LogInfo((object)"Doppelganger completed its staged valuable delivery.");
			_deliveryStage = DeliveryStage.None;
			_deliveryValuable = null;
			_deliveryObject = null;
			_deliveryCart = null;
			_deliveryExtraction = null;
			_deliveryTimer = 0f;
			EnterSearch(resetHostility: false);
		}

		private void CancelDelivery()
		{
			bool num = _deliveryStage != DeliveryStage.None;
			if ((Object)(object)_controller != (Object)null && _controller.HasGrabTarget)
			{
				_controller.EndDirectedGrabHost();
			}
			_deliveryStage = DeliveryStage.None;
			_deliveryValuable = null;
			_deliveryObject = null;
			_deliveryCart = null;
			_deliveryExtraction = null;
			_deliveryTimer = 0f;
			if (num && (Object)(object)_controller != (Object)null)
			{
				DoppelgangerDebugOverlay.Record(_controller, "DELIVERY", "entrega cancelada");
			}
		}

		private void ScanVision()
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: 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)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			PlayerAvatar val = null;
			PlayerAvatar val2 = null;
			Vector3 visibleTargetPoint = Vector3.zero;
			Vector3 visibleTargetPoint2 = Vector3.zero;
			float num = float.MaxValue;
			float num2 = float.MaxValue;
			if ((Object)(object)GameDirector.instance != (Object)null)
			{
				foreach (PlayerAvatar player in GameDirector.instance.PlayerList)
				{
					if (!IsValidPlayer(player))
					{
						continue;
					}
					float num3 = HorizontalDistance(Position, GetPlayerPhysicalPosition(player));
					if (num3 > 22f || !InsideFieldOfView(player))
					{
						continue;
					}
					if (TryGetVisiblePoint(player, lowEye: false, out var visiblePoint))
					{
						if (num3 < num)
						{
							val = player;
							num = num3;
							visibleTargetPoint = visiblePoint;
						}
					}
					else if ((player.isCrouching || player.isCrawling) && num3 <= 7f && TryGetVisiblePoint(player, lowEye: true, out visiblePoint) && num3 < num2)
					{
						val2 = player;
						num2 = num3;
						visibleTargetPoint2 = visiblePoint;
					}
				}
			}
			if ((Object)(object)val != (Object)null)
			{
				_inspectTarget = null;
				_combatTarget = val;
				_visibleTargetPoint = visibleTargetPoint;
				_visibilityGraceTimer = 0.4f;
				_targetVisible = true;
			}
			else if ((Object)(object)val2 != (Object)null)
			{
				if (!((Object)(object)_combatTarget == (Object)(object)val2) || !_targetVisible)
				{
					if ((Object)(object)_inspectTarget != (Object)(object)val2)
					{
						_inspectTarget = val2;
						_inspectTimer = 0.65f;
					}
					_visibleTargetPoint = visibleTargetPoint2;
					_targetVisible = false;
				}
			}
			else if (IsValidPlayer(_combatTarget) && _visibilityGraceTimer > 0f)
			{
				_targetVisible = true;
			}
			else
			{
				_targetVisible = false;
				_inspectTarget = null;
			}
		}

		private void InspectLowTarget()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: 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_002f: 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_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			if (!IsValidPlayer(_inspectTarget))
			{
				_inspectTarget = null;
				return;
			}
			PlayerAvatar inspectTarget = _inspectTarget;
			Vector3 val = ((_visibleTargetPoint != Vector3.zero) ? _visibleTargetPoint : GetLowTargetPoint(inspectTarget));
			Face(val);
			StopMoving();
			_controller.SetCombatPoseHost(sprinting: false, crouching: true, gunDrawn: false, val);
			_inspectTimer -= Time.deltaTime;
			if (!(_inspectTimer > 0f))
			{
				if (InsideFieldOfView(inspectTarget) && TryGetVisiblePoint(inspectTarget, lowEye: true, out var visiblePoint))
				{
					_combatTarget = inspectTarget;
					_targetVisible = true;
					_visibleTargetPoint = visiblePoint;
					_visibilityGraceTimer = 0.4f;
					_lastSeenPosition = visiblePoint;
					_lastSeenTimer = 10f;
				}
				_inspectTarget = null;
			}
		}

		private void EngageVisibleTarget(PlayerAvatar target)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = ((_visibleTargetPoint != Vector3.zero) ? _visibleTargetPoint : GetTargetPoint(target));
			float num = HorizontalDistance(Position, GetPlayerPhysicalPosition(target));
			Face(val);
			if (num <= 3f)
			{
				_gunMode = false;
				StopMoving();
				_aimTimer = 0f;
				_controller.SetCombatPoseHost(sprinting: false, target.isCrouching || target.isCrawling, gunDrawn: false, val);
				if (_controller.TryMeleeHost(target))
				{
					string text = (target.isCrawling ? "crawling" : (target.isCrouching ? "crouching" : "standing"));
					Plugin.Log.LogDebug((object)("Doppelganger struck " + text + " target \"" + target.playerName + "\"."));
				}
			}
			else if (num >= 5.5f && num <= 20f)
			{
				AimAndShoot(target, val);
			}
			else
			{
				_aimTimer = 0f;
				_gunMode = false;
				MoveTo(((Component)target).transform.position, 5.2f, sprint: true);
				TryJump(((Component)target).transform.position);
				_controller.SetCombatPoseHost(_lastMoveSprinting, crouching: false, gunDrawn: false, val);
			}
		}

		private void AimAndShoot(PlayerAvatar target, Vector3 targetPoint)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: 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_00b9: Unknown result type (might be due to invalid IL or missing references)
			StopMoving();
			_controller.SetCombatPoseHost(sprinting: false, crouching: false, gunDrawn: true, targetPoint);
			if (!_gunMode)
			{
				_gunMode = true;
				Plugin.Log.LogDebug((object)$"Doppelganger drew its handgun at {HorizontalDistance(Position, GetPlayerPhysicalPosition(target)):0.0}m.");
			}
			if (!(_shotCooldown > 0f))
			{
				_aimTimer += Time.deltaTime;
				if (!(_aimTimer < 0.45f) && (TryGetVisiblePoint(target, lowEye: false, out var visiblePoint) || TryGetVisiblePoint(target, lowEye: true, out visiblePoint)))
				{
					_aimTimer = 0f;
					_shotCooldown = 1.5f;
					_visibleTargetPoint = visiblePoint;
					bool flag = _controller.ShootHost(target, visiblePoint);
					Plugin.Log.LogDebug((object)("Doppelganger fired at \"" + target.playerName + "\" and " + (flag ? "hit a player" : "missed") + "."));
				}
			}
		}

		private void Roam()
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			_roamTimer -= Time.deltaTime;
			if (_roamTimer <= 0f || HorizontalDistance(Position, _roamPosition) <= 1.2f || (_enemy.HasNavMeshAgent && !_enemy.NavMeshAgent.HasPath()))
			{
				LevelPoint val = (((Object)(object)LevelGenerator.Instance != (Object)null) ? SemiFunc.LevelPointGet(Position, 6f, 18f) : null);
				NavMeshHit val2 = default(NavMeshHit);
				if ((Object)(object)val != (Object)null && NavMesh.SamplePosition(((Component)val).transform.position + Random.insideUnitSphere * 1.5f, ref val2, 4f, -1))
				{
					_roamPosition = ((NavMeshHit)(ref val2)).position;
					_roamTimer = Random.Range(5f, 10f);
				}
				else
				{
					_roamPosition = Position;
					_roamTimer = 2f;
				}
			}
			Face(_roamPosition);
			MoveTo(_roamPosition, 2.3f, sprint: false);
			_controller.SetCombatPoseHost(sprinting: false, crouching: false, gunDrawn: false, _roamPosition);
		}

		private void MoveTo(Vector3 destination, float speed, bool sprint)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: 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_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: 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_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: 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_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: 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_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: 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_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			_lastMoveSprinting = false;
			if (!_enemy.HasNavMeshAgent || (Object)(object)_enemy.NavMeshAgent == (Object)null || !EnsureAgentOnNavMesh())
			{
				return;
			}
			MonitorMovementProgress(destination);
			Vector3 val = GetHumanizedDestination(destination, sprint);
			bool forceDangerous = false;
			if (TryFindSafeGapTraversal(destination, out var approach, out var landing, out var jumpDistance))
			{
				forceDangerous = true;
				if (HorizontalDistance(Position, approach) <= 0.72f)
				{
					if (!TryStartManagedGapJump(landing, jumpDistance))
					{
						StopMoving();
					}
					return;
				}
				val = approach;
			}
			if (!TryResolveReachableDestination(val, 1.75f, out var reachable))
			{
				if (_stuckTimer >= 2.25f)
				{
					RecoverFromStuck(destination);
				}
				return;
			}
			if (!IsImmediateGroundedPath(reachable, out var unsafePoint))
			{
				Vector3 reachable2 = destination;
				if (!(HorizontalDistance(val, destination) > 0.2f) || !TryResolveReachableDestination(destination, 1.25f, out reachable2) || !IsImmediateGroundedPath(reachable2, out unsafePoint))
				{
					BlockUnsafeTraversal(destination, unsafePoint);
					return;
				}
				reachable = reachable2;
			}
			bool flag = UpdateTraversalRisk(reachable, forceDangerous);
			bool flag2 = sprint && !flag;
			float num = (flag ? Mathf.Min(speed, 1.4f) : speed);
			_lastMoveSprinting = flag2;
			_enemy.NavMeshAgent.UpdateAgent(num, flag2 ? 18f : (flag ? 5f : 8f));
			if (_destinationRefreshTimer <= 0f || HorizontalDistance(_lastIssuedDestination, reachable) > 0.4f || !HasUsableNavigationPath())
			{
				_enemy.NavMeshAgent.SetDestination(reachable);
				_lastIssuedDestination = reachable;
				_destinationRefreshTimer = 0.16f;
			}
			if (!flag2 && _enemy.HasRigidbody && (Object)(object)_enemy.Rigidbody != (Object)null)
			{
				_enemy.Rigidbody.IdleSet(0.1f);
			}
			TryJump(destination);
			if (!flag)
			{
				TryRandomPlayerJump(destination);
			}
		}

		private bool TryFindSafeGapTraversal(Vector3 destination, out Vector3 approach, out Vector3 landing, out float jumpDistance)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00a8: 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)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: 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_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: 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_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: 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_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Unknown result type (might be due to invalid IL or missing references)
			approach = Position;
			landing = Position;
			jumpDistance = 0f;
			if (_controller.HasGrabTarget || !_enemy.HasJump || (Object)(object)_enemy.Jump == (Object)null || !_enemy.HasGrounded || (Object)(object)_enemy.Grounded == (Object)null || !_enemy.Grounded.grounded || _enemy.Jump.jumping || HorizontalDistance(Position, destination) < 2f || HasReasonablePathTo(destination))
			{
				return false;
			}
			Vector3 val = destination - Position;
			val.y = 0f;
			if (((Vector3)(ref val)).sqrMagnitude < 0.01f)
			{
				return false;
			}
			((Vector3)(ref val)).Normalize();
			float num = Mathf.Min(9f, HorizontalDistance(Position, destination) - 0.25f);
			float num2 = -1f;
			int num3 = 0;
			for (float num4 = 0.55f; num4 <= num; num4 += 0.4f)
			{
				bool flag = HasGroundSupport(Position + val * num4, 1.8f);
				if (num2 < 0f)
				{
					if (!flag)
					{
						num2 = num4;
					}
					continue;
				}
				if (!flag)
				{
					num3 = 0;
					continue;
				}
				num3++;
				if (num3 < 2)
				{
					continue;
				}
				float num5 = num4 - 0.4f;
				float num6 = num5 - num2;
				if (num6 < 0.65f)
				{
					num2 = -1f;
					num3 = 0;
					continue;
				}
				if (num6 > 6.8f)
				{
					return false;
				}
				Vector3 requested = Position + val * Mathf.Max(0.15f, num2 - 0.55f);
				if (!TryResolveReachableDestination(requested, 0.65f, out approach))
				{
					return false;
				}
				if (!TryFindSafeGapLanding(Position, val, num5, out landing))
				{
					return false;
				}
				jumpDistance = HorizontalDistance(approach, landing);
				if (jumpDistance > 8.3f || !IsJumpArcClear(approach, landing, jumpDistance))
				{
					return false;
				}
				return true;
			}
			return false;
		}

		private bool TryFindSafeGapLanding(Vector3 origin, Vector3 direction, float firstLandingDistance, out Vector3 landing)
		{
			//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_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: 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_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: 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_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			landing = origin;
			Vector3 val = Vector3.Cross(Vector3.up, direction);
			Vector3 normalized = ((Vector3)(ref val)).normalized;
			float[] array = new float[3] { 0.35f, 0.7f, 1.05f };
			float[] array2 = new float[3] { 0f, 0.45f, -0.45f };
			float[] array3 = array;
			NavMeshHit val2 = default(NavMeshHit);
			foreach (float num in array3)
			{
				float[] array4 = array2;
				foreach (float num2 in array4)
				{
					if (NavMesh.SamplePosition(origin + direction * (firstLandingDistance + num) + normalized * num2, ref val2, 0.6f, -1) && !(Mathf.Abs(((NavMeshHit)(ref val2)).position.y - origin.y) > 1.8f) && HasOpenNavSpace(((NavMeshHit)(ref val2)).position, 0.32f) && HasGroundSupport(((NavMeshHit)(ref val2)).position, 1.4f))
					{
						landing = ((NavMeshHit)(ref val2)).position;
						return true;
					}
				}
			}
			return false;
		}

		private bool TryStartManagedGapJump(Vector3 landing, float jumpDistance)
		{
			//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)
			//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_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: 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)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			if (_managedGapCooldown > 0f || !_enemy.HasJump || (Object)(object)_enemy.Jump == (Object)null || !_enemy.HasRigidbody || (Object)(object)_enemy.Rigidbody == (Object)null || !_enemy.HasGrounded || (Object)(object)_enemy.Grounded == (Object)null || !_enemy.Grounded.grounded || _enemy.Jump.jumping || _enemy.Jump.gapJumpImpulse)
			{
				return false;
			}
			StopMoving();
			Vector3 val = landing - Position;
			val.y = 0f;
			if (((Vector3)(ref val)).sqrMagnitude < 0.01f)
			{
				return false;
			}
			((Vector3)(ref val)).Normalize();
			Face(landing);
			float num = Mathf.Lerp(5.2f, 7.1f, Mathf.InverseLerp(2f, 7.5f, jumpDistance));
			float num2 = Mathf.Lerp(5.8f, 9.4f, Mathf.InverseLerp(2f, 7.5f, jumpDistance));
			_enemy.Jump.gapJumpLandPosition = landing;
			_enemy.Jump.GapJumpOverride(0.7f, num, num2);
			_enemy.Jump.gapJumpImpulse = true;
			_managedGapLanding = landing;
			_managedGapStart = Position;
			_managedGapJumpActive = true;
			_managedGapSafetyTimer = 3.5f;
			_managedDoubleJumpPending = jumpDistance >= 4.6f || landing.y - Position.y > 0.7f;
			_managedDoubleJumpTimer = 0.3f;
			_managedGapCooldown = 2.5f;
			_jumpCheckTimer = 0.8f;
			_lastMoveSprinting = false;
			ResetStuckMonitor();
			DoppelgangerDebugOverlay.Record(_controller, "NAVEGAÇÃO", "salto seguro sobre void até " + FormatVector(landing) + " " + $"({jumpDistance:0.0}m" + (_managedDoubleJumpPending ? ", double jump preparado)" : ")"));
			return true;
		}

		private void UpdateManagedGapJump()
		{
			//IL_0058: 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_010f: 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_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			if (!_managedGapJumpActive || !_enemy.HasJump || (Object)(object)_enemy.Jump == (Object)null)
			{
				return;
			}
			_managedGapSafetyTimer -= Time.deltaTime;
			float num = Mathf.Min(_managedGapStart.y, _managedGapLanding.y);
			bool flag = Position.y < num - 0.75f;
			bool flag2 = _managedGapSafetyTimer <= 0f && !HasSafeGroundFootprint(Position);
			if (flag || flag2)
			{
				RecoverFailedManagedGapJump(flag ? "caiu abaixo da plataforma" : "não alcançou o piso no tempo seguro");
				return;
			}
			if (_managedDoubleJumpPending && _enemy.Jump.jumping)
			{
				_managedDoubleJumpTimer -= Time.deltaTime;
				if (_managedDoubleJumpTimer <= 0f && _enemy.HasRigidbody && (Object)(object)_enemy.Rigidbody != (Object)null)
				{
					Vector3 val = _managedGapLanding - ((Component)_enemy.Rigidbody).transform.position;
					val.y = 0f;
					float magnitude = ((Vector3)(ref val)).magnitude;
					if (magnitude > 1.2f)
					{
						((Vector3)(ref val)).Normalize();
						float num2 = Mathf.Clamp(magnitude * 0.3f, 1.25f, 2.35f);
						_enemy.Rigidbody.rb.AddForce(val * num2 + Vector3.up * 2.4f, (ForceMode)2);
						DoppelgangerDebugOverlay.Record(_controller, "NAVEGAÇÃO", $"double jump aplicado; destino a {magnitude:0.0}m");
					}
					_managedDoubleJumpPending = false;
				}
			}
			if (!_enemy.Jump.jumping && !_enemy.Jump.gapJumpImpulse)
			{
				_managedGapJumpActive = false;
				_managedDoubleJumpPending = false;
				_managedGapSafetyTimer = 0f;
			}
		}

		private void RecoverFailedManagedGapJump(string reason)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: 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_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = (HasSafeGroundFootprint(_managedGapLanding) ? _managedGapLanding : (_hasSafeNavPosition ? _lastSafeNavPosition : _managedGapStart));
			if (_enemy.HasJump && (Object)(object)_enemy.Jump != (Object)null)
			{
				_enemy.Jump.gapJumpImpulse = false;
				_enemy.Jump.JumpingDelaySet(false, (Type)0);
				_enemy.Jump.JumpingSet(false, (Type)0);
			}
			if (_enemy.HasRigidbody && (Object)(object)_enemy.Rigidbody != (Object)null && (Object)(object)_enemy.Rigidbody.rb != (Object)null)
			{
				_enemy.Rigidbody.rb.velocity = Vector3.zero;
				_enemy.Rigidbody.rb.angularVelocity = Vector3.zero;
			}
			if (_enemy.HasNavMeshAgent && (Object)(object)_enemy.NavMeshAgent != (Object)null)
			{
				_enemy.NavMeshAgent.Warp(val, true);
				_enemy.NavMeshAgent.ResetPath();
			}
			_enemy.EnemyTeleported(val);
			_managedGapJumpActive = false;
			_managedDoubleJumpPending = false;
			_managedGapSafetyTimer = 0f;
			_managedGapCooldown = Mathf.Max(_managedGapCooldown, 3f);
			_lastSafeNavPosition = val;
			_hasSafeNavPosition = true;
			ResetStuckMonitor();
			DoppelgangerDebugOverlay.Record(_controller, "NAVEGAÇÃO", "salto sobre void abortado com recuperação segura (" + reason + ")");
			Plugin.Log.LogWarning((object)("Recovered Doppelganger from a failed managed gap jump: " + reason + "."));
		}

		private bool HasReasonablePathTo(Vector3 destination)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Expected O, but got Unknown
			//IL_005e: 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_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_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: 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_00b0: 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)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			if (!_enemy.HasNavMeshAgent || (Object)(object)_enemy.NavMeshAgent == (Object)null)
			{
				return false;
			}
			NavMeshAgent agent = _enemy.NavMeshAgent.Agent;
			NavMeshHit val = default(NavMeshHit);
			if (!((Behaviour)agent).enabled || !agent.isOnNavMesh || !NavMesh.SamplePosition(destination, ref val, 1.5f, -1))
			{
				return false;
			}
			NavMeshPath val2 = new NavMeshPath();
			if (!agent.CalculatePath(((NavMeshHit)(ref val)).position, val2) || (int)val2.status != 0 || val2.corners.Length == 0)
			{
				return false;
			}
			float num = 0f;
			Vector3 val3 = Position;
			Vector3[] corners = val2.corners;
			foreach (Vector3 val4 in corners)
			{
				num += Vector3.Distance(val3, val4);
				val3 = val4;
			}
			float num2 = Vector3.Distance(Position, ((NavMeshHit)(ref val)).position);
			return num <= num2 + 4f;
		}

		private bool UpdateTraversalRisk(Vector3 destination, bool forceDangerous)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			if (forceDangerous || IsTraversalNearVoid(destination))
			{
				_dangerousTraversalTimer = 1.2f;
			}
			bool flag = _dangerousTraversalTimer > 0f;
			if (flag != _dangerousTraversal)
			{
				_dangerousTraversal = flag;
				DoppelgangerDebugOverlay.Record(_controller, "NAVEGAÇÃO", flag ? "área perigosa detectada; sprint suspenso" : "caminho seguro novamente; sprint liberado");
			}
			return flag;
		}

		private bool IsTraversalNearVoid(Vector3 destination)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//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_0055: 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_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_004c: 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_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = destination - Position;
			val.y = 0f;
			val = ((((Vector3)(ref val)).sqrMagnitude > 0.01f) ? ((Vector3)(ref val)).normalized : ((((Vector3)(ref _facing)).sqrMagnitude > 0.01f) ? ((Vector3)(ref _facing)).normalized : ((Component)this).transform.forward));
			if (!HasGroundSupport(Position + val * 0.8f, 1.8f))
			{
				return true;
			}
			int num = 0;
			for (int i = 0; i < 8; i++)
			{
				Vector3 val2 = Quaternion.AngleAxis((float)i * 45f, Vector3.up) * Vector3.forward;
				if (!HasGroundSupport(Position + val2 * 0.72