Decompiled source of TheMimic v1.0.1

MimicMonster.dll

Decompiled 14 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Voice;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.Events;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: AssemblyCompany("MimicMonster")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("MimicMonster")]
[assembly: AssemblyTitle("MimicMonster")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[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;
		}
	}
}
public class EnemyMimic : MonoBehaviour
{
	public enum State
	{
		Spawn,
		Idle,
		Roam,
		Stalk,
		SeekCorpse,
		Impersonate,
		Hunt,
		Jumpscare,
		Leave,
		Despawn,
		Stun
	}

	public bool debugSpawn;

	[Space]
	public State currentState;

	private bool stateImpulse;

	internal float stateTimer;

	[Space]
	public Enemy enemy;

	private PhotonView photonView;

	[Space]
	public SpringQuaternion horizontalRotationSpring;

	private Quaternion horizontalRotationTarget = Quaternion.identity;

	private float pitCheckTimer;

	private Vector3 leavePosition;

	[Header("Roam / Stalk")]
	public float roamSpeed = 3.5f;

	public float roamAcceleration = 8f;

	public float stalkSpeed = 2f;

	public float stalkAcceleration = 4f;

	public float lureHoldDistance = 8.5f;

	public float stalkTimeoutMax = 20f;

	private PlayerAvatar stalkTargetPlayer;

	private Vector3 stalkPoint;

	public float isolationWeight = 1f;

	public float proximityWeight = 0.6f;

	public float isolationDistanceCap = 30f;

	private float stalkTimer;

	[Header("SeekCorpse / Impersonate")]
	public float corpseDetectionRadius = 20f;

	public float corpseReachDistance = 1.5f;

	public float impersonateDuration = 2f;

	public Transform mimicVisualsRoot;

	public Transform disguiseRigParent;

	public GameObject disguiseRigTemplate;

	private GameObject disguiseRigInstance;

	private PlayerCosmetics disguiseCosmetics;

	private SkinnedMeshRenderer[] mimicRenderers;

	public float disguiseSwayCycle = 1.6f;

	public float disguiseSwayLeanDegrees = 3f;

	public float disguiseSwayBobMeters = 0.02f;

	private float disguiseSwayTime;

	private PlayerDeathHead corpseTarget;

	private static readonly HashSet<PlayerDeathHead> ClaimedHeads = new HashSet<PlayerDeathHead>();

	[Header("Hunt")]
	public float huntSpeed = 4.5f;

	public float huntAcceleration = 10f;

	public float huntProximityRevealDistance = 2.5f;

	[Header("Voice Mimicry")]
	public float voiceLureMinInterval = 12f;

	public float voiceLureMaxInterval = 24f;

	private float voiceLureTimer;

	private PlayerAvatar huntTarget;

	[Header("Jumpscare")]
	public Transform jumpscareFaceTransform;

	public HurtCollider hurtCollider;

	private float hurtColliderTimer;

	public Sound soundJumpscareSting;

	public AudioClip[] footstepClips;

	public AudioClip[] heavyFootstepClips;

	public AudioClip[] servoClips;

	private AudioSource footstepSource;

	private float footstepTimer;

	private bool footstepAltServo;

	private Vector3 footLastPos;

	private bool footPosInit;

	private Vector3 jumpscareLockPos;

	private bool jumpscareLockSet;

	private Vector3 mimicJumpscareLockPos;

	private Coroutine jumpscareVictimCo;

	private Transform footBoneL;

	private Transform footBoneR;

	private float footPrevYL;

	private float footPrevYR;

	private bool footDescL;

	private bool footDescR;

	private float footCdL;

	private float footCdR;

	public float jumpscareAnimDuration = 1.2f;

	public float jumpscareWindupDuration = 1f;

	public string jumpscareAnimatorTrigger = "Jumpscare";

	public Animator mimicAnimator;

	private PlayerAvatar jumpscareTarget;

	private bool jumpscareKillDone;

	private static bool loggedAnimParams;

	private Vector3 nativeLastPos;

	private bool nativeLastPosInit;

	private Transform jumpscareHeadBone;

	private static bool loggedAimBone;

	public bool debugForceSpawn;

	public float pounceRange = 7f;

	public float stalkDetectionRange = 22f;

	public static void ClearRunStatics()
	{
		ClaimedHeads.Clear();
	}

	private void Awake()
	{
		photonView = ((Component)this).GetComponent<PhotonView>();
		if (Object.op_Implicit((Object)(object)mimicVisualsRoot))
		{
			mimicRenderers = ((Component)mimicVisualsRoot).GetComponentsInChildren<SkinnedMeshRenderer>(true);
		}
	}

	private void Start()
	{
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: Expected O, but got Unknown
		//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cf: Expected O, but got Unknown
		//IL_014b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0155: Expected O, but got Unknown
		//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0102: Expected O, but got Unknown
		//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)enemy == (Object)null)
		{
			enemy = ((Component)this).GetComponent<Enemy>();
		}
		if ((Object)(object)enemy == (Object)null)
		{
			return;
		}
		if (enemy.HasStateSpawn && (Object)(object)enemy.StateSpawn != (Object)null && enemy.StateSpawn.OnSpawn != null)
		{
			enemy.StateSpawn.OnSpawn.AddListener(new UnityAction(OnSpawn));
		}
		if (enemy.HasHealth && (Object)(object)enemy.Health != (Object)null)
		{
			if (enemy.Health.onDeath != null)
			{
				enemy.Health.onDeath.AddListener(new UnityAction(OnDeath));
			}
			if (enemy.Health.onHurt != null)
			{
				enemy.Health.onHurt.AddListener(new UnityAction(OnHurt));
			}
		}
		if (enemy.HasStateInvestigate && (Object)(object)enemy.StateInvestigate != (Object)null && enemy.StateInvestigate.onInvestigateTriggered != null)
		{
			enemy.StateInvestigate.onInvestigateTriggered.AddListener(new UnityAction(OnInvestigate));
		}
		if (!loggedAnimParams && Object.op_Implicit((Object)(object)mimicAnimator) && (Object)(object)mimicAnimator.runtimeAnimatorController != (Object)null)
		{
			loggedAnimParams = true;
			StringBuilder stringBuilder = new StringBuilder("[EnemyMimic][AnimParams] native mimicAnimator params: ");
			AnimatorControllerParameter[] parameters = mimicAnimator.parameters;
			foreach (AnimatorControllerParameter val in parameters)
			{
				stringBuilder.Append(val.name).Append('(').Append(val.type)
					.Append(") ");
			}
			Debug.Log((object)stringBuilder.ToString(), (Object)(object)this);
		}
		if (Object.op_Implicit((Object)(object)mimicAnimator))
		{
			mimicAnimator.cullingMode = (AnimatorCullingMode)0;
		}
		jumpscareWindupDuration = 3f;
		jumpscareAnimDuration = 0.6f;
	}

	private void Update()
	{
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Invalid comparison between Unknown and I4
		HurtColliderTimer();
		DisguiseSwayLogic();
		NativeLocomotionTick();
		FootstepTick();
		if (SemiFunc.IsMasterClientOrSingleplayer())
		{
			if (enemy.IsStunned())
			{
				UpdateState(State.Stun);
			}
			if ((int)enemy.CurrentState == 11 && !enemy.IsStunned())
			{
				UpdateState(State.Despawn);
			}
			HorizontalRotationLogic();
			VoiceLureTick();
			switch (currentState)
			{
			case State.Spawn:
				StateSpawn();
				break;
			case State.Idle:
				StateIdle();
				break;
			case State.Roam:
				StateRoam();
				break;
			case State.Stalk:
				StateStalk();
				break;
			case State.SeekCorpse:
				StateSeekCorpse();
				break;
			case State.Impersonate:
				StateImpersonate();
				break;
			case State.Hunt:
				StateHunt();
				break;
			case State.Jumpscare:
				StateJumpscare();
				break;
			case State.Leave:
				StateLeave();
				break;
			case State.Despawn:
				StateDespawn();
				break;
			case State.Stun:
				StateStun();
				break;
			}
		}
	}

	private void StateSpawn()
	{
		if (stateImpulse)
		{
			stateImpulse = false;
			stateTimer = 1f;
		}
		stateTimer -= Time.deltaTime;
		if (stateTimer <= 0f)
		{
			UpdateState(State.Idle);
		}
	}

	private void StateIdle()
	{
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		if (stateImpulse)
		{
			stateImpulse = false;
			stateTimer = Random.Range(14f, 28f);
			enemy.NavMeshAgent.Warp(((Component)enemy.Rigidbody).transform.position, false);
			enemy.NavMeshAgent.ResetPath();
		}
		if (SemiFunc.EnemySpawnIdlePause())
		{
			return;
		}
		PlayerDeathHead val = TryFindCorpse(corpseDetectionRadius);
		if ((Object)(object)val != (Object)null)
		{
			ClaimCorpse(val);
			UpdateState(State.SeekCorpse);
		}
		else
		{
			if (PounceCheck())
			{
				return;
			}
			PlayerAvatar val2 = DetectStalkTarget();
			if ((Object)(object)val2 != (Object)null)
			{
				stalkTargetPlayer = val2;
				UpdateState(State.Stalk);
				return;
			}
			stateTimer -= Time.deltaTime;
			if (stateTimer <= 0f)
			{
				UpdateState(State.Roam);
			}
			if (SemiFunc.EnemyForceLeave(enemy))
			{
				UpdateState(State.Leave);
			}
		}
	}

	private void StateRoam()
	{
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_0101: Unknown result type (might be due to invalid IL or missing references)
		//IL_0127: Unknown result type (might be due to invalid IL or missing references)
		//IL_012c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0136: Unknown result type (might be due to invalid IL or missing references)
		//IL_013b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0151: Unknown result type (might be due to invalid IL or missing references)
		//IL_0156: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: Unknown result type (might be due to invalid IL or missing references)
		//IL_009b: Unknown result type (might be due to invalid IL or missing references)
		if (stateImpulse)
		{
			stateImpulse = false;
			stateTimer = 1f;
			bool flag = false;
			LevelPoint val = null;
			float num = -1f;
			for (int i = 0; i < 6; i++)
			{
				LevelPoint val2 = SemiFunc.LevelPointGet(((Component)this).transform.position, 8f, 40f);
				if (!Object.op_Implicit((Object)(object)val2))
				{
					continue;
				}
				float num2 = float.MaxValue;
				foreach (PlayerAvatar item in SemiFunc.PlayerGetList())
				{
					if (!((Object)(object)item == (Object)null) && !item.isDisabled)
					{
						float num3 = Vector3.Distance(((Component)val2).transform.position, ((Component)item).transform.position);
						if (num3 < num2)
						{
							num2 = num3;
						}
					}
				}
				if (num2 == float.MaxValue)
				{
					num2 = 999f;
				}
				if (num2 > num)
				{
					num = num2;
					val = val2;
				}
			}
			if (!Object.op_Implicit((Object)(object)val))
			{
				val = SemiFunc.LevelPointGet(((Component)this).transform.position, 0f, 999f);
			}
			NavMeshHit val3 = default(NavMeshHit);
			if (Object.op_Implicit((Object)(object)val) && NavMesh.SamplePosition(((Component)val).transform.position + Random.insideUnitSphere * 3f, ref val3, 5f, -1) && Physics.Raycast(((NavMeshHit)(ref val3)).position, Vector3.down, 5f, LayerMask.GetMask(new string[1] { "Default" })))
			{
				enemy.NavMeshAgent.UpdateAgent(roamSpeed, roamAcceleration);
				enemy.NavMeshAgent.SetDestination(((NavMeshHit)(ref val3)).position);
				flag = true;
			}
			if (!flag)
			{
				return;
			}
			pitCheckTimer = 0.1f;
			enemy.Rigidbody.notMovingTimer = 0f;
		}
		else
		{
			PlayerDeathHead val4 = TryFindCorpse(corpseDetectionRadius);
			if ((Object)(object)val4 != (Object)null)
			{
				ClaimCorpse(val4);
				UpdateState(State.SeekCorpse);
				return;
			}
			if (enemy.Rigidbody.notMovingTimer > 1f)
			{
				stateTimer -= Time.deltaTime;
			}
			if (PitCheckLogic())
			{
				enemy.NavMeshAgent.ResetPath();
			}
			if (stateTimer <= 0f || !enemy.NavMeshAgent.HasPath())
			{
				UpdateState(State.Idle);
			}
		}
		if (SemiFunc.EnemyForceLeave(enemy))
		{
			UpdateState(State.Leave);
		}
	}

	private void StateStalk()
	{
		//IL_0129: 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_01d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_0215: Unknown result type (might be due to invalid IL or missing references)
		//IL_0219: Unknown result type (might be due to invalid IL or missing references)
		//IL_0224: Unknown result type (might be due to invalid IL or missing references)
		//IL_0229: Unknown result type (might be due to invalid IL or missing references)
		//IL_022e: Unknown result type (might be due to invalid IL or missing references)
		//IL_020e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0213: 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_023a: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
		if (stateImpulse)
		{
			stateImpulse = false;
			stateTimer = 1f;
			stalkTimer = stalkTimeoutMax;
			enemy.NavMeshAgent.UpdateAgent(stalkSpeed, stalkAcceleration);
			pitCheckTimer = 0.1f;
			enemy.Rigidbody.notMovingTimer = 0f;
			voiceLureTimer = Random.Range(2.5f, 4.5f);
		}
		if (PounceCheck())
		{
			return;
		}
		if (!Object.op_Implicit((Object)(object)stalkTargetPlayer) || stalkTargetPlayer.isDisabled)
		{
			PlayerDeathHead val = TryFindCorpse(corpseDetectionRadius);
			if ((Object)(object)val != (Object)null)
			{
				ClaimCorpse(val);
				UpdateState(State.SeekCorpse);
			}
			else
			{
				UpdateState(State.Roam);
			}
			return;
		}
		PlayerDeathHead val2 = TryFindCorpse(corpseDetectionRadius);
		if ((Object)(object)val2 != (Object)null)
		{
			ClaimCorpse(val2);
			UpdateState(State.SeekCorpse);
			return;
		}
		stalkTimer -= Time.deltaTime;
		if (stalkTimer <= 0f)
		{
			UpdateState(State.Roam);
			return;
		}
		if (SemiFunc.PerSecond(1f, (Object)(object)this))
		{
			if (Vector3.Distance(((Component)this).transform.position, ((Component)stalkTargetPlayer).transform.position) <= stalkDetectionRange && IsIsolated(stalkTargetPlayer))
			{
				stalkTimer = stalkTimeoutMax;
			}
			Vector3 destination;
			if (enemy.HasOnScreen && enemy.OnScreen.OnScreenAny)
			{
				LevelPoint val3 = SemiFunc.LevelPointGetPlayerDistance(((Component)this).transform.position, 8f, 20f, false);
				destination = (Object.op_Implicit((Object)(object)val3) ? ((Component)val3).transform.position : ((Component)stalkTargetPlayer).transform.position);
			}
			else
			{
				Vector3 position = ((Component)stalkTargetPlayer).transform.position;
				Vector3 val4 = ((Component)this).transform.position - position;
				val4.y = 0f;
				if (((Vector3)(ref val4)).sqrMagnitude < 0.01f)
				{
					val4 = ((Component)this).transform.forward;
				}
				destination = position + ((Vector3)(ref val4)).normalized * lureHoldDistance;
			}
			enemy.NavMeshAgent.SetDestination(destination);
		}
		if (enemy.Rigidbody.notMovingTimer > 1f)
		{
			stateTimer -= Time.deltaTime;
		}
		PitCheckLogic();
		if (SemiFunc.EnemyForceLeave(enemy))
		{
			UpdateState(State.Leave);
		}
	}

	private void StateSeekCorpse()
	{
		//IL_009f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0123: Unknown result type (might be due to invalid IL or missing references)
		//IL_0174: Unknown result type (might be due to invalid IL or missing references)
		//IL_0184: Unknown result type (might be due to invalid IL or missing references)
		if (stateImpulse)
		{
			stateImpulse = false;
			stateTimer = 8f;
			if ((Object)(object)corpseTarget == (Object)null)
			{
				corpseTarget = TryFindCorpse(corpseDetectionRadius);
				if ((Object)(object)corpseTarget != (Object)null)
				{
					ClaimCorpse(corpseTarget);
				}
			}
			if ((Object)(object)corpseTarget == (Object)null)
			{
				UpdateState(State.Idle);
				return;
			}
			enemy.NavMeshAgent.UpdateAgent(huntSpeed, huntAcceleration);
			enemy.NavMeshAgent.SetDestination(((Component)corpseTarget).transform.position);
			pitCheckTimer = 0.1f;
			enemy.Rigidbody.notMovingTimer = 0f;
			return;
		}
		if ((Object)(object)corpseTarget == (Object)null || !corpseTarget.triggered || corpseTarget.overrideSpectated)
		{
			ReleaseCorpseClaim();
			UpdateState(State.Idle);
			return;
		}
		if (SemiFunc.PerSecond(2f, (Object)(object)this))
		{
			enemy.NavMeshAgent.SetDestination(((Component)corpseTarget).transform.position);
		}
		if (enemy.Rigidbody.notMovingTimer > 1f)
		{
			stateTimer -= Time.deltaTime;
		}
		if (PitCheckLogic())
		{
			enemy.NavMeshAgent.ResetPath();
		}
		if (Vector3.Distance(((Component)this).transform.position, ((Component)corpseTarget).transform.position) <= corpseReachDistance)
		{
			UpdateState(State.Impersonate);
		}
		else if (stateTimer <= 0f || !enemy.NavMeshAgent.HasPath())
		{
			ReleaseCorpseClaim();
			UpdateState(State.Idle);
		}
	}

	private void StateImpersonate()
	{
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
		if (stateImpulse)
		{
			stateImpulse = false;
			stateTimer = impersonateDuration;
			enemy.NavMeshAgent.Warp(((Component)enemy.Rigidbody).transform.position, false);
			enemy.NavMeshAgent.ResetPath();
			if ((Object)(object)corpseTarget == (Object)null || (Object)(object)corpseTarget.playerAvatar == (Object)null || (Object)(object)corpseTarget.playerCosmetics == (Object)null)
			{
				ReleaseCorpseClaim();
				UpdateState(State.Idle);
				return;
			}
			List<int> cosmeticEquippedRaw = corpseTarget.playerCosmetics.cosmeticEquippedRaw;
			int[] colorsEquipped = corpseTarget.playerCosmetics.colorsEquipped;
			if (SemiFunc.IsMultiplayer())
			{
				photonView.RPC("ImpersonateRPC", (RpcTarget)0, new object[2]
				{
					cosmeticEquippedRaw.ToArray(),
					colorsEquipped
				});
			}
			else
			{
				ImpersonateRPC(cosmeticEquippedRaw.ToArray(), colorsEquipped);
			}
		}
		else
		{
			stateTimer -= Time.deltaTime;
			if (stateTimer <= 0f)
			{
				UpdateState(State.Hunt);
			}
		}
	}

	[PunRPC]
	private void ImpersonateRPC(int[] cosmeticIds, int[] colorIds, PhotonMessageInfo info = default(PhotonMessageInfo))
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		if (SemiFunc.MasterOnlyRPC(info))
		{
			if (Object.op_Implicit((Object)(object)mimicVisualsRoot))
			{
				((Component)mimicVisualsRoot).gameObject.SetActive(false);
			}
			SetupDisguiseRig(new List<int>(cosmeticIds), colorIds);
		}
	}

	private void SetupDisguiseRig(List<int> cosmeticIds, int[] colorIds)
	{
		//IL_00c6: 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)
		Transform val = (((Object)(object)disguiseRigParent != (Object)null) ? disguiseRigParent : (((Object)(object)mimicVisualsRoot != (Object)null && (Object)(object)mimicVisualsRoot.parent != (Object)null) ? mimicVisualsRoot.parent : ((Component)this).transform));
		GameObject val2 = disguiseRigTemplate;
		if ((Object)(object)val2 == (Object)null)
		{
			val2 = FindLiveAvatarVisualsRig();
		}
		if ((Object)(object)val2 == (Object)null || (Object)(object)val == (Object)null)
		{
			Debug.LogWarning((object)"EnemyMimic: no disguise rig template and no live player rig to clone - Impersonate cannot build a disguise.", (Object)(object)this);
			return;
		}
		try
		{
			if (!Object.op_Implicit((Object)(object)disguiseRigInstance))
			{
				disguiseRigParent = val;
				((Component)disguiseRigParent).gameObject.SetActive(false);
				disguiseRigInstance = Object.Instantiate<GameObject>(val2, disguiseRigParent);
				disguiseRigInstance.transform.localPosition = Vector3.zero;
				disguiseRigInstance.transform.localRotation = Quaternion.identity;
				PhotonView[] componentsInChildren = disguiseRigInstance.GetComponentsInChildren<PhotonView>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					Object.Destroy((Object)(object)componentsInChildren[i]);
				}
				PlayerNameChecker[] componentsInChildren2 = disguiseRigInstance.GetComponentsInChildren<PlayerNameChecker>(true);
				foreach (PlayerNameChecker val3 in componentsInChildren2)
				{
					if ((Object)(object)val3 != (Object)null)
					{
						Object.Destroy((Object)(object)val3);
					}
				}
				PlayerAvatarVisuals[] componentsInChildren3 = disguiseRigInstance.GetComponentsInChildren<PlayerAvatarVisuals>(true);
				foreach (PlayerAvatarVisuals val4 in componentsInChildren3)
				{
					if ((Object)(object)val4 != (Object)null)
					{
						((Behaviour)val4).enabled = false;
						val4.playerAvatar = null;
					}
				}
				disguiseCosmetics = disguiseRigInstance.GetComponentInChildren<PlayerCosmetics>(true);
				if ((Object)(object)disguiseCosmetics != (Object)null)
				{
					disguiseCosmetics.firstSetup = false;
				}
				((Component)disguiseRigParent).gameObject.SetActive(true);
				if ((Object)(object)disguiseRigInstance.GetComponent<MimicDisguiseAnimDriver>() == (Object)null)
				{
					disguiseRigInstance.AddComponent<MimicDisguiseAnimDriver>();
				}
			}
			if (!Object.op_Implicit((Object)(object)disguiseCosmetics))
			{
				Debug.LogError((object)"EnemyMimic: disguiseRigTemplate has no PlayerCosmetics component anywhere in its hierarchy - cannot apply corpse identity.", (Object)(object)this);
				return;
			}
			if (disguiseCosmetics.cosmeticParents == null || disguiseCosmetics.cosmeticParents.Count == 0)
			{
				Debug.LogError((object)"EnemyMimic: disguiseRigTemplate's PlayerCosmetics.cosmeticParents is empty - SetupCosmetics will NRE inside InstantiateCosmetic() (confirmed failure mode, DECISIONS.md 21:5x). Wire cosmeticParents on the template prefab in the Editor before Impersonate can work.", (Object)(object)this);
				return;
			}
			disguiseCosmetics.SetupCosmetics(false, true, cosmeticIds);
			disguiseCosmetics.SetupColors(false, colorIds);
			Renderer[] componentsInChildren4 = disguiseRigInstance.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val5 in componentsInChildren4)
			{
				if (!((Object)(object)val5 == (Object)null))
				{
					val5.shadowCastingMode = (ShadowCastingMode)1;
					val5.forceRenderingOff = false;
				}
			}
			if (Object.op_Implicit((Object)(object)disguiseRigInstance))
			{
				disguiseRigInstance.SetActive(true);
			}
		}
		catch (Exception ex)
		{
			Debug.LogError((object)("EnemyMimic: disguise rig setup threw (cloned-rig detached-state?) - disguise skipped this attempt: " + ex));
		}
	}

	private GameObject FindLiveAvatarVisualsRig()
	{
		PlayerAvatar[] array = Object.FindObjectsOfType<PlayerAvatar>();
		foreach (PlayerAvatar val in array)
		{
			if (!((Object)(object)val == (Object)null))
			{
				PlayerCosmetics componentInChildren = ((Component)val).GetComponentInChildren<PlayerCosmetics>(true);
				if ((Object)(object)componentInChildren != (Object)null && componentInChildren.cosmeticParents != null && componentInChildren.cosmeticParents.Count > 0 && (Object)(object)componentInChildren.playerAvatarVisuals != (Object)null)
				{
					return ((Component)componentInChildren.playerAvatarVisuals).gameObject;
				}
			}
		}
		return null;
	}

	public void DebugForceVoiceLure()
	{
		//IL_015c: 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)
		PlayerAvatar instance = PlayerAvatar.instance;
		if ((Object)(object)instance == (Object)null || (Object)(object)instance.photonView == (Object)null)
		{
			Debug.LogError((object)"[EnemyMimic] DebugForceVoiceLure: no local PlayerAvatar.");
			return;
		}
		int num = 0;
		foreach (MimicVoiceCapture item in MimicVoiceCapture.All)
		{
			if ((Object)(object)item != (Object)null && item.IsLocalOwned)
			{
				num = item.SnippetCount + item.ChatLineCount;
				break;
			}
		}
		Debug.Log((object)$"[EnemyMimic] DebugForceVoiceLure: local='{((Object)instance).name}' has {num} captured snippet(s)/chat-line(s). Requesting playback from Mimic view {photonView.ViewID}. If 0, talk into your mic (or send a TTS-chat line) first, then press again.");
		if (num == 0)
		{
			foreach (MimicVoiceCapture item2 in MimicVoiceCapture.All)
			{
				if ((Object)(object)item2 != (Object)null && item2.IsLocalOwned)
				{
					item2.InjectDebugSnippet();
					break;
				}
			}
			Debug.Log((object)"[EnemyMimic] DebugForceVoiceLure: no real captured voice -> injected a synthetic test snippet so the Mimic-body playback can be verified without a mic.");
		}
		int viewID = photonView.ViewID;
		int viewID2 = instance.photonView.ViewID;
		MimicVoicePlayback.SoloFallbackMimic = ((Component)this).gameObject;
		if (SemiFunc.IsMultiplayer())
		{
			photonView.RPC("VoiceLureRequestRPC", (RpcTarget)0, new object[2] { viewID2, viewID });
		}
		else
		{
			VoiceLureRequestRPC(viewID2, viewID);
		}
	}

	public void DebugForceTTSLure()
	{
		//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
		PlayerAvatar instance = PlayerAvatar.instance;
		if ((Object)(object)instance == (Object)null || (Object)(object)instance.photonView == (Object)null)
		{
			Debug.LogError((object)"[EnemyMimic] DebugForceTTSLure: no local PlayerAvatar.");
			return;
		}
		foreach (MimicVoiceCapture item in MimicVoiceCapture.All)
		{
			if ((Object)(object)item != (Object)null && item.IsLocalOwned)
			{
				item.InjectDebugChatLine();
				break;
			}
		}
		int viewID = photonView.ViewID;
		int viewID2 = instance.photonView.ViewID;
		MimicVoicePlayback.SoloFallbackMimic = ((Component)this).gameObject;
		Debug.Log((object)$"[EnemyMimic] DebugForceTTSLure: forcing a TTS-chat fallback lure from Mimic view {viewID}.");
		if (SemiFunc.IsMultiplayer())
		{
			photonView.RPC("VoiceLureRequestRPC", (RpcTarget)0, new object[2] { viewID2, viewID });
		}
		else
		{
			VoiceLureRequestRPC(viewID2, viewID);
		}
	}

	public void DebugForceImpersonate(PlayerAvatar targetPlayer)
	{
		if ((Object)(object)targetPlayer == (Object)null || (Object)(object)targetPlayer.playerCosmetics == (Object)null)
		{
			Debug.LogError((object)"EnemyMimic.DebugForceImpersonate: targetPlayer or its playerCosmetics is null - cannot force a disguise.", (Object)(object)this);
			return;
		}
		List<int> cosmeticEquippedRaw = targetPlayer.playerCosmetics.cosmeticEquippedRaw;
		int[] colorsEquipped = targetPlayer.playerCosmetics.colorsEquipped;
		if (Object.op_Implicit((Object)(object)mimicVisualsRoot))
		{
			((Component)mimicVisualsRoot).gameObject.SetActive(false);
		}
		SetupDisguiseRig(cosmeticEquippedRaw, colorsEquipped);
		currentState = State.Impersonate;
		stateImpulse = false;
		stateTimer = impersonateDuration;
		string text = "(no animator)";
		if (Object.op_Implicit((Object)(object)mimicAnimator))
		{
			AnimatorClipInfo[] currentAnimatorClipInfo = mimicAnimator.GetCurrentAnimatorClipInfo(0);
			text = ((currentAnimatorClipInfo.Length != 0 && (Object)(object)((AnimatorClipInfo)(ref currentAnimatorClipInfo[0])).clip != (Object)null) ? ((Object)((AnimatorClipInfo)(ref currentAnimatorClipInfo[0])).clip).name : "(no clip)");
		}
		int num = (((Object)(object)disguiseCosmetics != (Object)null && disguiseCosmetics.cosmeticEquipped != null) ? disguiseCosmetics.cosmeticEquipped.Count : 0);
		Debug.Log((object)$"[EnemyMimic][DebugForceImpersonate] target='{((Object)targetPlayer).name}' rigInstantiated={(Object)(object)disguiseRigInstance != (Object)null} cosmeticsComponentPresent={(Object)(object)disguiseCosmetics != (Object)null} cosmeticIdsRead={cosmeticEquippedRaw?.Count ?? 0} cosmeticsActuallyApplied={num} animatorClip={text} nextTransition=Hunt in {impersonateDuration:F1}s (then proximity<={huntProximityRevealDistance:F1}m auto-triggers Jumpscare)", (Object)(object)this);
	}

	private void StateHunt()
	{
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: 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_00c3: 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_0100: Unknown result type (might be due to invalid IL or missing references)
		//IL_0151: Unknown result type (might be due to invalid IL or missing references)
		//IL_0161: Unknown result type (might be due to invalid IL or missing references)
		if (stateImpulse)
		{
			stateImpulse = false;
			stateTimer = 1f;
			huntTarget = SemiFunc.PlayerGetNearestPlayerAvatarWithinRange(999f, ((Component)this).transform.position, false, default(LayerMask));
			if ((Object)(object)huntTarget == (Object)null)
			{
				UpdateState(State.Leave);
				return;
			}
			enemy.NavMeshAgent.UpdateAgent(huntSpeed, huntAcceleration);
			pitCheckTimer = 0.1f;
			enemy.Rigidbody.notMovingTimer = 0f;
		}
		if ((Object)(object)huntTarget == (Object)null || huntTarget.isDisabled)
		{
			huntTarget = SemiFunc.PlayerGetNearestPlayerAvatarWithinRange(999f, ((Component)this).transform.position, false, default(LayerMask));
			if ((Object)(object)huntTarget == (Object)null)
			{
				UpdateState(State.Leave);
				return;
			}
		}
		enemy.NavMeshAgent.SetDestination(((Component)huntTarget).transform.position);
		if (enemy.Rigidbody.notMovingTimer > 1f)
		{
			stateTimer -= Time.deltaTime;
		}
		if (PitCheckLogic())
		{
			enemy.NavMeshAgent.ResetPath();
		}
		if (Vector3.Distance(((Component)this).transform.position, ((Component)huntTarget).transform.position) <= huntProximityRevealDistance)
		{
			jumpscareTarget = huntTarget;
			UpdateState(State.Jumpscare);
		}
		else if (SemiFunc.EnemyForceLeave(enemy))
		{
			UpdateState(State.Leave);
		}
	}

	private void StateJumpscare()
	{
		//IL_023c: Unknown result type (might be due to invalid IL or missing references)
		//IL_024e: 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_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_00b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_0112: 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_011d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0122: Unknown result type (might be due to invalid IL or missing references)
		//IL_0127: Unknown result type (might be due to invalid IL or missing references)
		//IL_0128: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_014b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0158: Unknown result type (might be due to invalid IL or missing references)
		//IL_015f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0160: Unknown result type (might be due to invalid IL or missing references)
		//IL_0170: Unknown result type (might be due to invalid IL or missing references)
		//IL_0175: Unknown result type (might be due to invalid IL or missing references)
		//IL_0176: Unknown result type (might be due to invalid IL or missing references)
		//IL_017b: Unknown result type (might be due to invalid IL or missing references)
		//IL_013a: Unknown result type (might be due to invalid IL or missing references)
		//IL_013f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0199: Unknown result type (might be due to invalid IL or missing references)
		//IL_019e: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01af: 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_0206: Unknown result type (might be due to invalid IL or missing references)
		if (stateImpulse)
		{
			stateImpulse = false;
			stateTimer = jumpscareWindupDuration;
			jumpscareKillDone = false;
			enemy.NavMeshAgent.Warp(((Component)enemy.Rigidbody).transform.position, false);
			enemy.NavMeshAgent.ResetPath();
			if ((Object)(object)jumpscareTarget == (Object)null || jumpscareTarget.isDisabled)
			{
				UpdateState(State.Hunt);
				return;
			}
			Vector3 val = ((jumpscareTarget.isLocal && Object.op_Implicit((Object)(object)Camera.main)) ? ((Component)Camera.main).transform.forward : ((Component)jumpscareTarget).transform.forward);
			val.y = 0f;
			if (((Vector3)(ref val)).sqrMagnitude < 0.01f)
			{
				val = ((Component)this).transform.position - ((Component)jumpscareTarget).transform.position;
			}
			val.y = 0f;
			((Vector3)(ref val)).Normalize();
			Vector3 val2 = ((Component)jumpscareTarget).transform.position + val * 1.7f;
			NavMeshHit val3 = default(NavMeshHit);
			if (NavMesh.SamplePosition(val2, ref val3, 2.5f, -1))
			{
				val2 = ((NavMeshHit)(ref val3)).position;
			}
			enemy.NavMeshAgent.Warp(val2, false);
			((Component)this).transform.position = val2;
			mimicJumpscareLockPos = val2;
			Vector3 val4 = ((Component)jumpscareTarget).transform.position - val2;
			val4.y = 0f;
			if (((Vector3)(ref val4)).sqrMagnitude > 0.001f)
			{
				horizontalRotationTarget = Quaternion.LookRotation(((Vector3)(ref val4)).normalized);
				((Component)this).transform.rotation = horizontalRotationTarget;
			}
			jumpscareLockSet = false;
			int viewID = jumpscareTarget.photonView.ViewID;
			if (SemiFunc.IsMultiplayer())
			{
				photonView.RPC("JumpscarePresentationRPC", (RpcTarget)0, new object[1] { viewID });
			}
			else
			{
				JumpscarePresentationRPC(viewID);
			}
			return;
		}
		stateTimer -= Time.deltaTime;
		enemy.NavMeshAgent.ResetPath();
		enemy.NavMeshAgent.Warp(mimicJumpscareLockPos, false);
		((Component)this).transform.position = mimicJumpscareLockPos;
		if (stateTimer > 0f)
		{
			return;
		}
		if (!jumpscareKillDone)
		{
			jumpscareKillDone = true;
			stateTimer = jumpscareAnimDuration;
			if ((Object)(object)jumpscareTarget == (Object)null || jumpscareTarget.isDisabled)
			{
				UpdateState(State.Hunt);
				return;
			}
			int viewID2 = jumpscareTarget.photonView.ViewID;
			if (SemiFunc.IsMultiplayer())
			{
				photonView.RPC("JumpscareKillRPC", (RpcTarget)0, new object[1] { viewID2 });
			}
			else
			{
				JumpscareKillRPC(viewID2);
			}
		}
		else
		{
			if (Object.op_Implicit((Object)(object)hurtCollider))
			{
				((Component)hurtCollider).gameObject.SetActive(false);
			}
			ReleaseCorpseClaim();
			corpseTarget = null;
			UpdateState(State.SeekCorpse);
		}
	}

	[PunRPC]
	private void JumpscarePresentationRPC(int targetViewId, PhotonMessageInfo info = default(PhotonMessageInfo))
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: Unknown result type (might be due to invalid IL or missing references)
		//IL_020d: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
		if (!SemiFunc.MasterOnlyRPC(info))
		{
			return;
		}
		PlayerAvatar val = null;
		foreach (PlayerAvatar item in SemiFunc.PlayerGetList())
		{
			if (item.photonView.ViewID == targetViewId)
			{
				val = item;
				break;
			}
		}
		jumpscareTarget = val;
		if ((Object)(object)val == (Object)null)
		{
			return;
		}
		Vector3 jumpscareAimPoint = GetJumpscareAimPoint();
		if (val.isLocal && Object.op_Implicit((Object)(object)CameraAim.Instance))
		{
			CameraAim.Instance.AimTargetSet(jumpscareAimPoint, jumpscareWindupDuration + jumpscareAnimDuration + 0.3f, 90f, ((Component)this).gameObject, 100);
			CameraAim.Instance.OverrideAimStop();
			if (jumpscareVictimCo != null)
			{
				((MonoBehaviour)this).StopCoroutine(jumpscareVictimCo);
			}
			jumpscareLockSet = false;
			jumpscareVictimCo = ((MonoBehaviour)this).StartCoroutine(JumpscareVictimDriveCo());
		}
		if (Object.op_Implicit((Object)(object)mimicVisualsRoot))
		{
			((Component)mimicVisualsRoot).gameObject.SetActive(true);
		}
		if (Object.op_Implicit((Object)(object)disguiseRigInstance))
		{
			disguiseRigInstance.SetActive(false);
		}
		if (Object.op_Implicit((Object)(object)mimicAnimator) && !string.IsNullOrEmpty(jumpscareAnimatorTrigger))
		{
			mimicAnimator.cullingMode = (AnimatorCullingMode)0;
			mimicAnimator.speed = 1f;
			mimicAnimator.ResetTrigger(jumpscareAnimatorTrigger);
			mimicAnimator.Play("Jumpscare", 0, 0f);
			mimicAnimator.Update(0f);
			mimicAnimator.SetTrigger(jumpscareAnimatorTrigger);
			string arg = "(none)";
			AnimatorClipInfo[] currentAnimatorClipInfo = mimicAnimator.GetCurrentAnimatorClipInfo(0);
			if (currentAnimatorClipInfo != null && currentAnimatorClipInfo.Length != 0 && (Object)(object)((AnimatorClipInfo)(ref currentAnimatorClipInfo[0])).clip != (Object)null)
			{
				arg = ((Object)((AnimatorClipInfo)(ref currentAnimatorClipInfo[0])).clip).name;
			}
			Debug.Log((object)$"[EnemyMimic][Jumpscare] revealed native model, played Jumpscare (resulting clip='{arg}') trigger='{jumpscareAnimatorTrigger}' aimPoint={jumpscareAimPoint}", (Object)(object)this);
		}
		if (soundJumpscareSting != null)
		{
			soundJumpscareSting.Play(((Component)this).transform.position, 1f, 1f, 1f, 1f);
		}
	}

	private Vector3 GetJumpscareAimPoint()
	{
		//IL_00d2: 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_00f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0106: Unknown result type (might be due to invalid IL or missing references)
		//IL_010b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)jumpscareHeadBone == (Object)null)
		{
			jumpscareHeadBone = FindDeepChild(((Object)(object)mimicVisualsRoot != (Object)null) ? mimicVisualsRoot : ((Component)this).transform, "head_jnt");
			if ((Object)(object)jumpscareHeadBone == (Object)null)
			{
				jumpscareHeadBone = FindDeepChild(((Component)this).transform, "head_jnt");
			}
		}
		if (!loggedAimBone)
		{
			loggedAimBone = true;
			Debug.Log((object)($"[EnemyMimic][AimBone] head_jnt found={(Object)(object)jumpscareHeadBone != (Object)null} " + (((Object)(object)jumpscareHeadBone != (Object)null) ? $"pos={jumpscareHeadBone.position}" : "(falling back)")));
		}
		if (Object.op_Implicit((Object)(object)jumpscareHeadBone))
		{
			return jumpscareHeadBone.position;
		}
		if (Object.op_Implicit((Object)(object)jumpscareFaceTransform))
		{
			return jumpscareFaceTransform.position;
		}
		return ((Component)this).transform.position + Vector3.up * 1.7f;
	}

	private static Transform FindDeepChild(Transform root, string name)
	{
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Expected O, but got Unknown
		if ((Object)(object)root == (Object)null)
		{
			return null;
		}
		if (((Object)root).name == name)
		{
			return root;
		}
		foreach (Transform item in root)
		{
			Transform val = FindDeepChild(item, name);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
		}
		return null;
	}

	private IEnumerator JumpscareVictimDriveCo()
	{
		float t = jumpscareWindupDuration + jumpscareAnimDuration + 0.1f;
		while (t > 0f)
		{
			t -= Time.deltaTime;
			if (Object.op_Implicit((Object)(object)CameraAim.Instance))
			{
				CameraAim.Instance.OverrideAimStop();
				CameraAim.Instance.AimTargetSet(GetJumpscareAimPoint(), 0.25f, 90f, ((Component)this).gameObject, 100);
			}
			if (Object.op_Implicit((Object)(object)PlayerController.instance) && Object.op_Implicit((Object)(object)PlayerController.instance.rb))
			{
				Rigidbody rb = PlayerController.instance.rb;
				if (!jumpscareLockSet)
				{
					jumpscareLockPos = rb.position;
					jumpscareLockSet = true;
				}
				Vector3 position = rb.position;
				position.x = jumpscareLockPos.x;
				position.z = jumpscareLockPos.z;
				if (Object.op_Implicit((Object)(object)jumpscareHeadBone) && Object.op_Implicit((Object)(object)jumpscareTarget) && Object.op_Implicit((Object)(object)jumpscareTarget.PlayerVisionTarget))
				{
					float y = jumpscareTarget.PlayerVisionTarget.VisionTransform.position.y;
					float num = jumpscareHeadBone.position.y - y;
					if (num > 0.03f)
					{
						position.y += Mathf.Min(num, 2f) * 0.4f;
					}
				}
				rb.position = position;
				rb.velocity = Vector3.zero;
			}
			yield return null;
		}
		jumpscareVictimCo = null;
	}

	[PunRPC]
	private void JumpscareKillRPC(int targetViewId, PhotonMessageInfo info = default(PhotonMessageInfo))
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
		if (!SemiFunc.MasterOnlyRPC(info))
		{
			return;
		}
		PlayerAvatar val = null;
		foreach (PlayerAvatar item in SemiFunc.PlayerGetList())
		{
			if (item.photonView.ViewID == targetViewId)
			{
				val = item;
				break;
			}
		}
		if (!((Object)(object)val == (Object)null))
		{
			if (Object.op_Implicit((Object)(object)hurtCollider))
			{
				((Component)hurtCollider).transform.position = val.PlayerVisionTarget.VisionTransform.position;
				Transform transform = ((Component)hurtCollider).transform;
				Vector3 val2 = ((Component)val).transform.position - ((Component)this).transform.position;
				transform.rotation = Quaternion.LookRotation(((Vector3)(ref val2)).normalized);
				((Component)hurtCollider).gameObject.SetActive(true);
				hurtColliderTimer = jumpscareAnimDuration;
				Debug.Log((object)$"[EnemyMimic][JumpscareKill] hurtCollider ENABLED at {((Component)hurtCollider).transform.position} vs target '{((Object)val).name}' (playerKill collider fired; expect PlayerHurt/death this frame)", (Object)(object)this);
			}
			else
			{
				Debug.LogError((object)"[EnemyMimic][JumpscareKill] hurtCollider is NULL - prefab has no playerKill HurtCollider child, so NO KILL will land. This is the C3 gap.");
			}
		}
	}

	private void StateLeave()
	{
		//IL_0115: 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_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_016b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0171: 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_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_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)
		if (stateImpulse)
		{
			enemy.NavMeshAgent.Warp(((Component)enemy.Rigidbody).transform.position, false);
			enemy.NavMeshAgent.ResetPath();
			if (!enemy.EnemyParent.playerClose)
			{
				UpdateState(State.Idle);
				return;
			}
			bool flag = false;
			LevelPoint val = SemiFunc.LevelPointGetPlayerDistance(((Component)this).transform.position, 25f, 50f, false);
			if (!Object.op_Implicit((Object)(object)val))
			{
				val = SemiFunc.LevelPointGetFurthestFromPlayer(((Component)this).transform.position, 5f);
			}
			NavMeshHit val2 = default(NavMeshHit);
			if (Object.op_Implicit((Object)(object)val) && NavMesh.SamplePosition(((Component)val).transform.position, ref val2, 5f, -1) && Physics.Raycast(((NavMeshHit)(ref val2)).position, Vector3.down, 5f, LayerMask.GetMask(new string[1] { "Default" })))
			{
				leavePosition = ((NavMeshHit)(ref val2)).position;
				flag = true;
			}
			if (!flag)
			{
				return;
			}
			stateImpulse = false;
			stateTimer = 5f;
		}
		enemy.NavMeshAgent.SetDestination(leavePosition);
		if (enemy.Rigidbody.notMovingTimer > 2f)
		{
			stateTimer -= Time.deltaTime;
		}
		if (PitCheckLogic())
		{
			stateImpulse = true;
		}
		else if (stateTimer <= 0f || Vector3.Distance(((Component)this).transform.position, leavePosition) < 1f)
		{
			UpdateState(State.Idle);
		}
	}

	private void StateDespawn()
	{
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		if (stateImpulse)
		{
			stateImpulse = false;
			enemy.NavMeshAgent.Warp(((Component)enemy.Rigidbody).transform.position, false);
			enemy.NavMeshAgent.ResetPath();
			ReleaseCorpseClaim();
		}
	}

	private void StateStun()
	{
		if (!enemy.IsStunned())
		{
			UpdateState(State.Idle);
		}
	}

	public void OnSpawn()
	{
		//IL_006e: 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)
		if (!debugForceSpawn && SemiFunc.IsMasterClientOrSingleplayer() && SemiFunc.PlayerGetAll().Count < 2)
		{
			Debug.Log((object)"[EnemyMimic] no-solo-spawn: <2 players, despawning this natural spawn (design: no solo spawn).", (Object)(object)this);
			enemy.EnemyParent.Despawn();
		}
		else if (SemiFunc.IsMasterClientOrSingleplayer() && SemiFunc.EnemySpawn(enemy))
		{
			if (SemiFunc.IsMultiplayer())
			{
				photonView.RPC("ResetVisualsRPC", (RpcTarget)0, Array.Empty<object>());
			}
			else
			{
				ResetVisualsRPC();
			}
			ReleaseCorpseClaim();
			UpdateState(State.Spawn);
		}
	}

	[PunRPC]
	private void ResetVisualsRPC(PhotonMessageInfo info = default(PhotonMessageInfo))
	{
		if (Object.op_Implicit((Object)(object)mimicVisualsRoot))
		{
			((Component)mimicVisualsRoot).gameObject.SetActive(true);
		}
		if (Object.op_Implicit((Object)(object)disguiseRigInstance))
		{
			Object.Destroy((Object)(object)disguiseRigInstance);
			disguiseRigInstance = null;
			disguiseCosmetics = null;
		}
	}

	public void OnHurt()
	{
		if (Object.op_Implicit((Object)(object)enemy) && enemy.HasHealth && (Object)(object)enemy.Health != (Object)null)
		{
			Debug.Log((object)$"[EnemyMimic][OnHurt] healthCurrent={enemy.Health.healthCurrent}/{enemy.Health.health} (damage landed - Mimic IS weapon-vulnerable)", (Object)(object)this);
		}
		if (SemiFunc.IsMasterClientOrSingleplayer() && currentState == State.Leave)
		{
			UpdateState(State.Idle);
		}
	}

	public void OnDeath()
	{
		if (SemiFunc.IsMasterClientOrSingleplayer())
		{
			ReleaseCorpseClaim();
			enemy.EnemyParent.Despawn();
		}
	}

	public void OnInvestigate()
	{
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		if (SemiFunc.IsMasterClientOrSingleplayer() && enemy.Rigidbody.timeSinceStun > 1.5f && (currentState == State.Idle || currentState == State.Roam || currentState == State.Stalk))
		{
			stalkPoint = enemy.StateInvestigate.onInvestigateTriggeredPosition;
			stalkTargetPlayer = FindPlayerNearPoint(stalkPoint);
			if ((Object)(object)stalkTargetPlayer != (Object)null)
			{
				UpdateState(State.Stalk);
			}
		}
	}

	private void UpdateState(State _state)
	{
		//IL_00b7: 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)
		if (SemiFunc.IsMasterClientOrSingleplayer() && _state != currentState)
		{
			Debug.Log((object)$"[EnemyMimic][State] {currentState} -> {_state}  (view {photonView.ViewID}, disguised={Object.op_Implicit((Object)(object)disguiseRigInstance)})");
			currentState = _state;
			stateImpulse = true;
			stateTimer = 0f;
			if (GameManager.Multiplayer())
			{
				photonView.RPC("UpdateStateRPC", (RpcTarget)0, new object[1] { currentState });
			}
			else
			{
				UpdateStateRPC(currentState);
			}
		}
	}

	[PunRPC]
	private void UpdateStateRPC(State _state, PhotonMessageInfo _info = default(PhotonMessageInfo))
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		if (SemiFunc.MasterOnlyRPC(_info))
		{
			currentState = _state;
		}
	}

	private void HorizontalRotationLogic()
	{
		//IL_0088: Unknown result type (might be due to invalid IL or missing references)
		//IL_008d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		//IL_005e: Unknown result type (might be due to invalid IL or missing references)
		//IL_017b: 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_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_010c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0111: 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_00e5: Unknown result type (might be due to invalid IL or missing references)
		if (currentState == State.Jumpscare && Object.op_Implicit((Object)(object)jumpscareTarget))
		{
			Vector3 val = ((Component)jumpscareTarget).transform.position - ((Component)this).transform.position;
			val.y = 0f;
			if (((Vector3)(ref val)).sqrMagnitude > 0.0001f)
			{
				horizontalRotationTarget = Quaternion.LookRotation(((Vector3)(ref val)).normalized);
			}
			horizontalRotationSpring.speed = 25f;
			horizontalRotationSpring.damping = 0.85f;
		}
		else
		{
			Vector3 val2 = Vector3.zero;
			if ((Object)(object)enemy.NavMeshAgent != (Object)null && (Object)(object)enemy.NavMeshAgent.Agent != (Object)null && enemy.NavMeshAgent.Agent.isOnNavMesh)
			{
				val2 = enemy.NavMeshAgent.Agent.desiredVelocity;
			}
			if (((Vector3)(ref val2)).magnitude < 0.5f && enemy.HasRigidbody)
			{
				val2 = enemy.Rigidbody.velocity;
			}
			val2.y = 0f;
			if (((Vector3)(ref val2)).magnitude > 0.6f)
			{
				horizontalRotationTarget = Quaternion.LookRotation(((Vector3)(ref val2)).normalized);
				horizontalRotationSpring.speed = ((currentState == State.Stalk) ? 4f : 6f);
				horizontalRotationSpring.damping = 0.7f;
			}
		}
		((Component)this).transform.rotation = SemiFunc.SpringQuaternionGet(horizontalRotationSpring, horizontalRotationTarget, -1f);
	}

	private bool PitCheckLogic()
	{
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_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_0070: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0084: Unknown result type (might be due to invalid IL or missing references)
		//IL_0089: Unknown result type (might be due to invalid IL or missing references)
		//IL_0093: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b6: 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_00c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
		if (pitCheckTimer <= 0f)
		{
			Vector3 normalized = ((Vector3)(ref enemy.NavMeshAgent.AgentVelocity)).normalized;
			if (((Vector3)(ref normalized)).magnitude > 0.1f)
			{
				pitCheckTimer = 0.5f;
				Vector3 normalized2 = ((Vector3)(ref enemy.NavMeshAgent.AgentVelocity)).normalized;
				normalized2.y = 0f;
				bool num = Physics.Raycast(((Component)this).transform.position + normalized2 + Vector3.up * 1f, Vector3.down, 5f, LayerMask.op_Implicit(SemiFunc.LayerMaskGetVisionObstruct()));
				if (!num)
				{
					enemy.NavMeshAgent.Warp(((Component)this).transform.position - normalized2 * 0.5f, false);
					enemy.NavMeshAgent.ResetPath();
					enemy.NavMeshAgent.Agent.velocity = Vector3.zero;
				}
				return !num;
			}
		}
		pitCheckTimer -= Time.deltaTime;
		return false;
	}

	private void FootstepTick()
	{
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: 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_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		if (footstepClips == null || footstepClips.Length == 0 || currentState == State.Jumpscare)
		{
			return;
		}
		Vector3 position = ((Component)this).transform.position;
		if (!footPosInit)
		{
			footLastPos = position;
			footPosInit = true;
			return;
		}
		Vector3 val = position - footLastPos;
		val.y = 0f;
		footLastPos = position;
		float num = Mathf.Max(Time.deltaTime, 1E-05f);
		float num2 = ((Vector3)(ref val)).magnitude / num;
		if (num2 > 20f)
		{
			return;
		}
		footCdL -= num;
		footCdR -= num;
		if (!(num2 < 0.4f))
		{
			Transform root = (((Object)(object)mimicVisualsRoot != (Object)null) ? mimicVisualsRoot : ((Component)this).transform);
			if ((Object)(object)footBoneL == (Object)null)
			{
				footBoneL = FindDeepChild(root, "L_foot_jnt");
			}
			if ((Object)(object)footBoneR == (Object)null)
			{
				footBoneR = FindDeepChild(root, "R_foot_jnt");
			}
			ProcessFootPlant(footBoneL, ref footPrevYL, ref footDescL, ref footCdL, num2);
			ProcessFootPlant(footBoneR, ref footPrevYR, ref footDescR, ref footCdR, num2);
		}
	}

	private void ProcessFootPlant(Transform foot, ref float prevY, ref bool descending, ref float cooldown, float spd)
	{
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)foot == (Object)null)
		{
			return;
		}
		float y = foot.position.y;
		float num = y - prevY;
		prevY = y;
		if (num < -0.0004f)
		{
			descending = true;
		}
		else if (descending && num > 0.0004f && cooldown <= 0f)
		{
			descending = false;
			cooldown = 0.14f;
			EnsureFootstepSource();
			bool flag = spd > 3.2f && heavyFootstepClips != null && heavyFootstepClips.Length != 0;
			AudioClip[] array = (flag ? heavyFootstepClips : footstepClips);
			footstepSource.PlayOneShot(array[Random.Range(0, array.Length)], flag ? 0.3f : 0.2f);
			if (servoClips != null && servoClips.Length != 0)
			{
				footstepSource.PlayOneShot(servoClips[Random.Range(0, servoClips.Length)], 0.15f);
			}
		}
	}

	private void EnsureFootstepSource()
	{
		if (!((Object)(object)footstepSource != (Object)null))
		{
			footstepSource = ((Component)this).gameObject.AddComponent<AudioSource>();
			footstepSource.spatialBlend = 1f;
			footstepSource.minDistance = 2f;
			footstepSource.maxDistance = 32f;
			footstepSource.rolloffMode = (AudioRolloffMode)1;
			footstepSource.playOnAwake = false;
			footstepSource.dopplerLevel = 0f;
		}
	}

	private void NativeLocomotionTick()
	{
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: 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_007d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		if (!Object.op_Implicit((Object)(object)mimicAnimator) || currentState == State.Jumpscare)
		{
			return;
		}
		if (!Object.op_Implicit((Object)(object)mimicVisualsRoot) || !((Component)mimicVisualsRoot).gameObject.activeInHierarchy)
		{
			nativeLastPosInit = false;
			return;
		}
		Vector3 position = ((Component)this).transform.position;
		if (!nativeLastPosInit)
		{
			nativeLastPos = position;
			nativeLastPosInit = true;
			return;
		}
		Vector3 val = position - nativeLastPos;
		val.y = 0f;
		nativeLastPos = position;
		float num = Mathf.Max(Time.deltaTime, 1E-05f);
		float num2 = ((Vector3)(ref val)).magnitude / num;
		if (!(num2 > 20f))
		{
			mimicAnimator.SetFloat("Speed", num2, 0.3f, num);
			if (Object.op_Implicit((Object)(object)enemy))
			{
				mimicAnimator.SetBool("Stunned", enemy.IsStunned());
			}
		}
	}

	private void DisguiseSwayLogic()
	{
		//IL_0076: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		if (Object.op_Implicit((Object)(object)disguiseRigInstance) && disguiseRigInstance.activeInHierarchy)
		{
			disguiseSwayTime += Time.deltaTime;
			float num = disguiseSwayTime / disguiseSwayCycle * (MathF.PI * 2f);
			float num2 = Mathf.Sin(num) * disguiseSwayLeanDegrees;
			float num3 = Mathf.Abs(Mathf.Sin(num)) * disguiseSwayBobMeters;
			disguiseRigInstance.transform.localRotation = Quaternion.Euler(0f, 0f, num2);
			disguiseRigInstance.transform.localPosition = new Vector3(0f, num3, 0f);
		}
	}

	private void HurtColliderTimer()
	{
		if (hurtColliderTimer > 0f)
		{
			hurtColliderTimer -= Time.deltaTime;
			if (hurtColliderTimer <= 0f && Object.op_Implicit((Object)(object)hurtCollider))
			{
				((Component)hurtCollider).gameObject.SetActive(false);
			}
		}
	}

	private PlayerDeathHead TryFindCorpse(float maxDistance)
	{
		//IL_0062: 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)
		PlayerDeathHead result = null;
		float num = maxDistance;
		foreach (PlayerAvatar item in SemiFunc.PlayerGetList())
		{
			if (!item.isDisabled)
			{
				continue;
			}
			PlayerDeathHead playerDeathHead = item.playerDeathHead;
			if (Object.op_Implicit((Object)(object)playerDeathHead) && playerDeathHead.triggered && !playerDeathHead.overrideSpectated && !ClaimedHeads.Contains(playerDeathHead))
			{
				float num2 = Vector3.Distance(((Component)enemy.Rigidbody).transform.position, ((Component)playerDeathHead).transform.position);
				if (num2 < num)
				{
					num = num2;
					result = playerDeathHead;
				}
			}
		}
		return result;
	}

	private void ClaimCorpse(PlayerDeathHead head)
	{
		corpseTarget = head;
		ClaimedHeads.Add(head);
	}

	private void ReleaseCorpseClaim()
	{
		if ((Object)(object)corpseTarget != (Object)null)
		{
			ClaimedHeads.Remove(corpseTarget);
		}
		corpseTarget = null;
	}

	private PlayerAvatar FindPlayerNearPoint(Vector3 point)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		Collider[] array = Physics.OverlapSphere(point, 1.5f, LayerMask.GetMask(new string[1] { "Player" }) + LayerMask.GetMask(new string[1] { "PhysGrabObject" }));
		foreach (Collider val in array)
		{
			if (((Component)val).CompareTag("Player"))
			{
				PlayerController componentInParent = ((Component)val).GetComponentInParent<PlayerController>();
				if (Object.op_Implicit((Object)(object)componentInParent))
				{
					return componentInParent.playerAvatarScript;
				}
				PlayerAvatar componentInParent2 = ((Component)val).GetComponentInParent<PlayerAvatar>();
				if (Object.op_Implicit((Object)(object)componentInParent2))
				{
					return componentInParent2;
				}
			}
			else
			{
				PlayerTumble componentInParent3 = ((Component)val).GetComponentInParent<PlayerTumble>();
				if (Object.op_Implicit((Object)(object)componentInParent3))
				{
					return componentInParent3.playerAvatar;
				}
			}
		}
		return null;
	}

	private PlayerAvatar SelectBestLureTarget()
	{
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0099: 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)
		List<PlayerAvatar> list = SemiFunc.PlayerGetList();
		PlayerAvatar result = null;
		float num = float.MinValue;
		foreach (PlayerAvatar item in list)
		{
			if ((Object)(object)item == (Object)null || item.isDisabled)
			{
				continue;
			}
			float num2 = Vector3.Distance(((Component)this).transform.position, ((Component)item).transform.position);
			float num3 = float.MaxValue;
			foreach (PlayerAvatar item2 in list)
			{
				if (!((Object)(object)item2 == (Object)null) && !((Object)(object)item2 == (Object)(object)item) && !item2.isDisabled)
				{
					float num4 = Vector3.Distance(((Component)item).transform.position, ((Component)item2).transform.position);
					if (num4 < num3)
					{
						num3 = num4;
					}
				}
			}
			if (num3 == float.MaxValue)
			{
				num3 = isolationDistanceCap;
			}
			float num5 = Mathf.Min(num3, isolationDistanceCap);
			float num6 = 0f - num2;
			float num7 = isolationWeight * num5 + proximityWeight * num6;
			if (num7 > num)
			{
				num = num7;
				result = item;
			}
		}
		return result;
	}

	private PlayerAvatar DetectStalkTarget()
	{
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		PlayerAvatar val = SelectBestLureTarget();
		if ((Object)(object)val == (Object)null)
		{
			return null;
		}
		if (Vector3.Distance(((Component)this).transform.position, ((Component)val).transform.position) > stalkDetectionRange)
		{
			return null;
		}
		if (!IsIsolated(val))
		{
			return null;
		}
		return val;
	}

	private bool PounceCheck()
	{
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		PlayerAvatar val = SelectBestLureTarget();
		if ((Object)(object)val == (Object)null)
		{
			return false;
		}
		if (Vector3.Distance(((Component)this).transform.position, ((Component)val).transform.position) > pounceRange)
		{
			return false;
		}
		if (!IsIsolated(val))
		{
			return false;
		}
		huntTarget = val;
		UpdateState(State.Hunt);
		return true;
	}

	private bool IsIsolated(PlayerAvatar p)
	{
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)p == (Object)null)
		{
			return false;
		}
		float num = float.MaxValue;
		foreach (PlayerAvatar item in SemiFunc.PlayerGetList())
		{
			if (!((Object)(object)item == (Object)null) && !((Object)(object)item == (Object)(object)p) && !item.isDisabled)
			{
				float num2 = Vector3.Distance(((Component)p).transform.position, ((Component)item).transform.position);
				if (num2 < num)
				{
					num = num2;
				}
			}
		}
		return num > isolationDistanceCap * 0.5f;
	}

	private void VoiceLureTick()
	{
		//IL_0255: Unknown result type (might be due to invalid IL or missing references)
		//IL_025b: Unknown result type (might be due to invalid IL or missing references)
		if (voiceLureTimer > 0f)
		{
			voiceLureTimer -= Time.deltaTime;
			return;
		}
		voiceLureTimer = Random.Range(voiceLureMinInterval, voiceLureMaxInterval);
		PlayerAvatar val = null;
		val = ((currentState == State.Impersonate && (Object)(object)corpseTarget != (Object)null && (Object)(object)corpseTarget.playerAvatar != (Object)null) ? corpseTarget.playerAvatar : ((currentState == State.Hunt && (Object)(object)huntTarget != (Object)null) ? huntTarget : ((currentState != State.Stalk || !((Object)(object)stalkTargetPlayer != (Object)null)) ? SelectBestLureTarget() : stalkTargetPlayer)));
		if ((Object)(object)val == (Object)null || (Object)(object)val.photonView == (Object)null)
		{
			return;
		}
		if (debugForceSpawn && !MimicVoiceCapture.VoiceViablePlayers.Contains(val.photonView.ViewID))
		{
			foreach (MimicVoiceCapture item in MimicVoiceCapture.All)
			{
				if ((Object)(object)item != (Object)null && item.IsLocalOwned && (Object)(object)item.PlayerAvatarRef == (Object)(object)val)
				{
					item.InjectDebugSnippet();
					break;
				}
			}
		}
		if (currentState != State.Impersonate && currentState != State.Hunt && !MimicVoiceCapture.VoiceViablePlayers.Contains(val.photonView.ViewID))
		{
			PlayerAvatar val2 = null;
			foreach (PlayerAvatar item2 in SemiFunc.PlayerGetList())
			{
				if (!((Object)(object)item2 == (Object)null) && !item2.isDisabled && !((Object)(object)item2.photonView == (Object)null) && MimicVoiceCapture.VoiceViablePlayers.Contains(item2.photonView.ViewID))
				{
					val2 = item2;
					break;
				}
			}
			if ((Object)(object)val2 == (Object)null)
			{
				return;
			}
			val = val2;
		}
		int viewID = photonView.ViewID;
		int viewID2 = val.photonView.ViewID;
		MimicVoicePlayback.SoloFallbackMimic = ((Component)this).gameObject;
		if (SemiFunc.IsMultiplayer())
		{
			photonView.RPC("VoiceLureRequestRPC", (RpcTarget)0, new object[2] { viewID2, viewID });
		}
		else
		{
			VoiceLureRequestRPC(viewID2, viewID);
		}
	}

	[PunRPC]
	private void VoiceLureRequestRPC(int playerViewId, int enemyViewId, PhotonMessageInfo info = default(PhotonMessageInfo))
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		if (SemiFunc.MasterOnlyRPC(info))
		{
			MimicVoiceCapture.RequestCaptureForMimic(playerViewId, enemyViewId);
		}
	}
}
public class MimicDisguiseAnimDriver : MonoBehaviour
{
	private Animator anim;

	private Vector3 lastPos;

	private bool moving;

	private bool sprinting;

	private static readonly string[] ClearBools = new string[10] { "Crouching", "Crawling", "Grabbing", "Jumping", "Falling", "Sliding", "Tumbling", "TumblingMove", "Turning", "Sprinting" };

	private void OnEnable()
	{
		//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)
		anim = ((Component)this).GetComponent<Animator>();
		if ((Object)(object)anim == (Object)null)
		{
			anim = ((Component)this).GetComponentInChildren<Animator>(true);
		}
		if ((Object)(object)anim == (Object)null)
		{
			((Behaviour)this).enabled = false;
			return;
		}
		anim.cullingMode = (AnimatorCullingMode)0;
		anim.speed = 1f;
		anim.Rebind();
		anim.Update(0f);
		string[] clearBools = ClearBools;
		foreach (string text in clearBools)
		{
			anim.SetBool(text, false);
		}
		moving = false;
		sprinting = false;
		lastPos = ((Component)this).transform.position;
	}

	private void Update()
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)anim == (Object)null)
		{
			return;
		}
		Vector3 val = ((Component)this).transform.position - lastPos;
		val.y = 0f;
		lastPos = ((Component)this).transform.position;
		float num = Mathf.Max(Time.deltaTime, 1E-05f);
		float num2 = ((Vector3)(ref val)).magnitude / num;
		if (num2 > 20f)
		{
			return;
		}
		if (moving)
		{
			if (num2 < 0.15f)
			{
				moving = false;
			}
		}
		else if (num2 > 0.35f)
		{
			moving = true;
		}
		anim.SetBool("Moving", moving);
		bool flag = moving && num2 > 4f;
		if (flag && !sprinting)
		{
			anim.SetTrigger("SprintingImpulse");
		}
		if (!flag && sprinting)
		{
			anim.ResetTrigger("SprintingImpulse");
		}
		sprinting = flag;
		anim.SetBool("Sprinting", flag);
	}
}
public class MimicVoiceCapture : MonoBehaviour
{
	private PlayerAvatar playerAvatar;

	private PhotonView view;

	private const int SampleRate = 48000;

	private const float SnippetSeconds = 2.5f;

	private const int MaxSnippets = 6;

	private float[] captureBuffer;

	private int capturePos;

	private bool capturing;

	private readonly List<float[]> snippets = new List<float[]>();

	private float recaptureCooldown;

	private readonly List<byte[]> rxChunks = new List<byte[]>();

	private int rxExpected;

	private int rxEnemyViewId;

	internal static readonly List<MimicVoiceCapture> All = new List<MimicVoiceCapture>();

	private const int MaxChatLines = 6;

	private readonly List<string> chatLines = new List<string>();

	internal static readonly HashSet<int> VoiceViablePlayers = new HashSet<int>();

	private bool reportedViable;

	internal bool IsLocalOwned
	{
		get
		{
			if ((Object)(object)view != (Object)null)
			{
				if (SemiFunc.IsMultiplayer())
				{
					return view.IsMine;
				}
				return true;
			}
			return false;
		}
	}

	internal int SnippetCount => snippets.Count;

	internal PlayerAvatar PlayerAvatarRef => playerAvatar;

	internal int ChatLineCount => chatLines.Count;

	private void Awake()
	{
		playerAvatar = ((Component)this).GetComponent<PlayerAvatar>();
		view = ((Component)this).GetComponent<PhotonView>();
		All.Add(this);
	}

	internal static void RequestCaptureForMimic(int playerViewId, int enemyViewId)
	{
		foreach (MimicVoiceCapture item in All)
		{
			if ((Object)(object)item != (Object)null && (Object)(object)item.view != (Object)null && item.view.ViewID == playerViewId)
			{
				item.BroadcastRandomSnippet(enemyViewId);
				return;
			}
		}
		Debug.LogWarning((object)$"[MimicVoice] No capture instance found for player view {playerViewId}.");
	}

	private void OnDestroy()
	{
		All.Remove(this);
	}

	private void Update()
	{
		if (recaptureCooldown > 0f)
		{
			recaptureCooldown -= Time.deltaTime;
		}
	}

	internal void InjectDebugSnippet()
	{
		int num = 96000;
		float[] array = new float[num];
		for (int i = 0; i < num; i++)
		{
			float num2 = (float)i / 48000f;
			float num3 = 180f + 40f * Mathf.Sin(num2 * 6f);
			array[i] = 0.45f * (Mathf.Sin(MathF.PI * 2f * num3 * num2) + 0.4f * Mathf.Sin(MathF.PI * 2f * num3 * 2f * num2)) * (0.6f + 0.4f * Mathf.Sin(num2 * 10f));
		}
		if (snippets.Count >= 6)
		{
			snippets.RemoveAt(0);
		}
		snippets.Add(array);
		ReportViable();
		Debug.Log((object)"[MimicVoice] DEBUG: injected a synthetic 2s voice snippet (no mic needed) - press the lure to hear it from the Mimic's body.");
	}

	internal void InjectDebugChatLine()
	{
		snippets.Clear();
		CaptureChatLine("hey, I found a bunch of loot back here - come help me carry it");
		Debug.Log((object)"[MimicVoice] DEBUG: seeded a synthetic TTS-chat line + cleared the voice ring - press the lure to hear the Mimic SPEAK it (TTS fallback rung).");
	}

	internal void CaptureChatLine(string text)
	{
		if (!string.IsNullOrWhiteSpace(text))
		{
			if (chatLines.Count >= 6)
			{
				chatLines.RemoveAt(0);
			}
			chatLines.Add(text);
			Debug.Log((object)string.Format("[MimicVoice] captured TTS-chat line #{0} of local player (\"{1}\").", chatLines.Count, (text.Length > 40) ? (text.Substring(0, 40) + "...") : text));
			ReportViable();
		}
	}

	private void ReportViable()
	{
		if (!reportedViable && !((Object)(object)view == (Object)null) && (snippets.Count != 0 || chatLines.Count != 0))
		{
			reportedViable = true;
			int viewID = view.ViewID;
			VoiceViablePlayers.Add(viewID);
			if (SemiFunc.IsMultiplayer())
			{
				view.RPC("VoiceViableRPC", (RpcTarget)0, new object[1] { viewID });
			}
		}
	}

	[PunRPC]
	private void VoiceViableRPC(int playerViewId, PhotonMessageInfo info = default(PhotonMessageInfo))
	{
		VoiceViablePlayers.Add(playerViewId);
	}

	internal void ProcessVoiceData(short[] voiceData)
	{
		if (!IsLocalOwned || (Object)(object)playerAvatar == (Object)null || (Object)(object)playerAvatar.voiceChat == (Object)null)
		{
			return;
		}
		if (playerAvatar.voiceChat.isTalking && !capturing && recaptureCooldown <= 0f)
		{
			capturing = true;
			captureBuffer = new float[120000];
			capturePos = 0;
		}
		if (!capturing)
		{
			return;
		}
		int num = Mathf.Min(voiceData.Length, captureBuffer.Length - capturePos);
		for (int i = 0; i < num; i++)
		{
			captureBuffer[capturePos + i] = (float)voiceData[i] / 32768f;
		}
		capturePos += num;
		if (capturePos >= captureBuffer.Length)
		{
			capturing = false;
			recaptureCooldown = 8f;
			if (snippets.Count >= 6)
			{
				snippets.RemoveAt(0);
			}
			snippets.Add(captureBuffer);
			captureBuffer = null;
			Debug.Log((object)$"[MimicVoice] captured snippet #{snippets.Count} of local player voice ({2.5f:F1}s).");
			ReportViable();
		}
	}

	internal void BroadcastRandomSnippet(int enemyViewId)
	{
		//IL_0115: 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)
		if (snippets.Count == 0)
		{
			if (chatLines.Count > 0)
			{
				BroadcastRandomChatLine(enemyViewId);
			}
			else
			{
				Debug.Log((object)"[MimicVoice] lure requested for this player but no mic snippets OR TTS-chat lines captured yet (normal in solo / before anyone talks or types).");
			}
			return;
		}
		float[] array = snippets[Random.Range(0, snippets.Count)];
		byte[] array2 = new byte[array.Length * 2];
		for (int i = 0; i < array.Length; i++)
		{
			short num = (short)(Mathf.Clamp(array[i], -1f, 1f) * 32767f);
			array2[i * 2] = (byte)(num & 0xFF);
			array2[i * 2 + 1] = (byte)((num >> 8) & 0xFF);
		}
		int num2 = (array2.Length + 8192 - 1) / 8192;
		if (SemiFunc.IsMultiplayer())
		{
			((MonoBehaviour)this).StartCoroutine(SendChunksPaced(array2, num2, 8192, enemyViewId));
			return;
		}
		for (int j = 0; j < num2; j++)
		{
			int num3 = Mathf.Min(8192, array2.Length - j * 8192);
			byte[] array3 = new byte[num3];
			Array.Copy(array2, j * 8192, array3, 0, num3);
			VoiceChunkRPC(array3, j, num2, 48000, enemyViewId);
		}
		Debug.Log((object)$"[MimicVoice] broadcast snippet in {num2} chunk(s) for Mimic view {enemyViewId} (solo, inline).");
	}

	private IEnumerator SendChunksPaced(byte[] bytes, int total, int chunkSize, int enemyViewId)
	{
		for (int c = 0; c < total; c++)
		{
			int num = Mathf.Min(chunkSize, bytes.Length - c * chunkSize);
			byte[] array = new byte[num];
			Array.Copy(bytes, c * chunkSize, array, 0, num);
			if ((Object)(object)view == (Object)null)
			{
				yield break;
			}
			view.RPC("VoiceChunkRPC", (RpcTarget)0, new object[5] { array, c, total, 48000, enemyViewId });
			if ((c & 1) == 1)
			{
				yield return (object)new WaitForSecondsRealtime(0.09f);
			}
		}
		Debug.Log((object)$"[MimicVoice] broadcast snippet in {total} paced chunk(s) for Mimic view {enemyViewId}.");
	}

	private void BroadcastRandomChatLine(int enemyViewId)
	{
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: Unknown result type (might be due to invalid IL or missing references)
		if (chatLines.Count != 0)
		{
			string text = chatLines[Random.Range(0, chatLines.Count)];
			int num = 0;
			if (SemiFunc.IsMultiplayer())
			{
				view.RPC("TTSChatRPC", (RpcTarget)0, new object[3] { text, num, enemyViewId });
			}
			else
			{
				TTSChatRPC(text, num, enemyViewId);
			}
			Debug.Log((object)$"[MimicVoice] broadcast TTS-chat line for Mimic view {enemyViewId}: {((text.Length > 40) ? text.Substring(0, 40) : text)}");
		}
	}

	[PunRPC]
	private void TTSChatRPC(string text, int voiceIndex, int enemyViewId, PhotonMessageInfo info = default(PhotonMessageInfo))
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		if (!SemiFunc.IsMultiplayer() || SemiFunc.OwnerOnlyRPC(info, view))
		{
			MimicTTSPlayback.Speak(text, voiceIndex, enemyViewId);
		}
	}

	[PunRPC]
	private void VoiceChunkRPC(byte[] chunk, int chunkIndex, int totalChunks, int sampleRate, int enemyViewId, PhotonMessageInfo info = default(PhotonMessageInfo))
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		if (SemiFunc.IsMultiplayer() && !SemiFunc.OwnerOnlyRPC(info, view))
		{
			return;
		}
		if (chunkIndex == 0)
		{
			rxChunks.Clear();
			rxExpected = totalChunks;
			rxEnemyViewId = enemyViewId;
		}
		if (chunkIndex >= rxExpected)
		{
			return;
		}
		while (rxChunks.Count <= chunkIndex)
		{
			rxChunks.Add(null);
		}
		rxChunks[chunkIndex] = chunk;
		if (rxChunks.Count < rxExpected)
		{
			return;
		}
		foreach (byte[] rxChunk in rxChunks)
		{
			if (rxChunk == null)
			{
				return;
			}
		}
		int num = 0;
		foreach (byte[] rxChunk2 in rxChunks)
		{
			num += rxChunk2.Length;
		}
		byte[] array = new byte[num];
		int num2 = 0;
		foreach (byte[] rxChunk3 in rxChunks)
		{
			Array.Copy(rxChunk3, 0, array, num2, rxChunk3.Length);
			num2 += rxChunk3.Length;
		}
		rxChunks.Clear();
		MimicVoicePlayback.PlayOnMimic(array, sampleRate, rxEnemyViewId, playerAvatar);
	}
}
public static class MimicVoicePlayback
{
	public static GameObject SoloFallbackMimic;

	public static void PlayOnMimic(byte[] audioData, int sampleRate, int enemyViewId, PlayerAvatar anyAvatarForMixer)
	{
		//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
		PhotonView val = PhotonView.Find(enemyViewId);
		GameObject val2 = (((Object)(object)val != (Object)null) ? ((Component)val).gameObject : SoloFallbackMimic);
		if ((Object)(object)val2 == (Object)null)
		{
			Debug.LogWarning((object)$"[MimicVoice] playback: Mimic view {enemyViewId} not found and no solo fallback - dropping snippet.");
			return;
		}
		int num = audioData.Length / 2;
		float[] array = new float[num];
		for (int i = 0; i < num; i++)
		{
			array[i] = (float)(short)(audioData[i * 2] | (audioData[i * 2 + 1] << 8)) / 32768f;
		}
		array = LowPass(array, 4500f, sampleRate);
		EdgeFade(array, (int)((float)sampleRate * 0.02f));
		AudioClip val3 = AudioClip.Create("MimicVoiceLure", array.Length, 1, sampleRate, false);
		val3.SetData(array, 0);
		Transform val4 = val2.transform.Find("MimicVoiceSource");
		if ((Object)(object)val4 == (Object)null)
		{
			GameObject val5 = new GameObject("MimicVoiceSource");
			val5.transform.SetParent(val2.transform, false);
			val4 = val5.transform;
		}
		AudioSource val6 = ((Component)val4).GetComponent<AudioSource>();
		if ((Object)(object)val6 == (Object)null)
		{
			val6 = ((Component)val4).gameObject.AddComponent<AudioSource>();
		}
		val6.clip = val3;
		val6.volume = 0.9f;
		val6.spatialBlend = 1f;
		val6.dopplerLevel = 0.5f;
		val6.minDistance = 1f;
		val6.maxDistance = 20f;
		val6.rolloffMode = (AudioRolloffMode)1;
		if ((Object)(object)anyAvatarForMixer != (Object)null && (Object)(object)anyAvatarForMixer.voiceChat != (Object)null && (Object)(object)anyAvatarForMixer.voiceChat.mixerMicrophoneSound != (Object)null)
		{
			val6.outputAudioMixerGroup = anyAvatarForMixer.voiceChat.mixerMicrophoneSound;
		}
		val6.Play();
		Debug.Log((object)$"[MimicVoice] playing {(float)array.Length / (float)sampleRate:F1}s lure from Mimic view {enemyViewId}.");
	}

	private static float[] LowPass(float[] input, float cutoff, int sampleRate)
	{
		float num = 1f / (MathF.PI * 2f * cutoff);
		float num2 = 1f / (float)sampleRate;
		float num3 = num2 / (num + num2);
		float[] array = new float[input.Length];
		float num4 = 0f;
		for (int i = 0; i < input.Length; i++)
		{
			num4 = (array[i] = num4 + num3 * (input[i] - num4));
		}
		return array;
	}

	private static void EdgeFade(float[] data, int fadeSamples)
	{
		for (int i = 0; i < fadeSamples && i < data.Length; i++)
		{
			float num = (float)i / (float)fadeSamples;
			data[i] *= num;
			data[data.Length - 1 - i] *= num;
		}
	}
}
[HarmonyPatch(typeof(PlayerAvatar), "Awake")]
internal static class MimicVoice_PlayerAvatarAwakePatch
{
	private static void Postfix(PlayerAvatar __instance)
	{
		if ((Object)(object)((Component)__instance).GetComponent<MimicVoiceCapture>() == (Object)null)
		{
			((Component)__instance).gameObject.AddComponent<MimicVoiceCapture>();
		}
	}
}
[HarmonyPatch(typeof(LocalVoiceFramed<short>), "PushDataAsync")]
internal static class MimicVoice_PushDataPatch
{
	private static void Prefix(short[] buf)
	{
		foreach (MimicVoiceCapture item in MimicVoiceCapture.All)
		{
			if ((Object)(object)item != (Object)null && item.IsLocalOwned)
			{
				item.ProcessVoiceData(buf);
				break;
			}
		}
	}
}
[HarmonyPatch(typeof(TTSVoice), "TTSSpeakNow")]
internal static class MimicVoice_TTSCapturePatch
{
	private static void Postfix(TTSVoice __instance, string text)
	{
		if ((Object)(object)__instance == (Object)null || (Object)(object)__instance.playerAvatar == (Object)null || string.IsNullOrWhiteSpace(text))
		{
			return;
		}
		foreach (MimicVoiceCapture item in MimicVoiceCapture.All)
		{
			if ((Object)(object)item != (Object)null && item.IsLocalOwned && (Object)(object)item.PlayerAvatarRef == (Object)(object)__instance.playerAvatar)
			{
				item.CaptureChatLine(text);
				break;
			}
		}
	}
}
public static class MimicTTSPlayback
{
	private static readonly Dictionary<int, TTSVoice> perMimic = new Dictionary<int, TTSVoice>();

	public static void ClearRunStatics()
	{
		perMimic.Clear();
	}

	public static void Speak(string text, int voiceIndex, int enemyViewId)
	{
		if (string.IsNullOrWhiteSpace(text))
		{
			return;
		}
		PhotonView val = PhotonView.Find(enemyViewId);
		GameObject val2 = (((Object)(object)val != (Object)null) ? ((Component)val).gameObject : MimicVoicePlayback.SoloFallbackMimic);
		if ((Object)(object)val2 == (Object)null)
		{
			Debug.LogWarning((object)$"[MimicVoice] TTS-chat: Mimic view {enemyViewId} not found and no solo fallback.");
			return;
		}
		TTSVoice orCreate = GetOrCreate(val2, enemyViewId);
		if ((Object)(object)orCreate == (Object)null)
		{
			Debug.LogWarning((object)"[MimicVoice] TTS-chat: no TTSVoice template to clone (no live player TTSVoice found).");
			return;
		}
		orCreate.setVoice(Mathf.Clamp(voiceIndex, 0, 1));
		orCreate.TTSSpeakNow(text, false);
		Debug.Log((object)string.Format("[MimicVoice] Mimic speaking TTS-chat line from its body (view {0}): \"{1}\".", enemyViewId, (text.Length > 40) ? (text.Substring(0, 40) + "...") : text));
	}

	private static TTSVoice GetOrCreate(GameObject mimic, int enemyViewId)
	{
		//IL_016d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0177: Unknown result type (might be due to invalid IL or missing references)
		if (perMimic.TryGetValue(enemyViewId, out var value) && (Object)(object)value != (Object)null)
		{
			return value;
		}
		TTSVoice val = null;
		TTSVoice[] array = Object.FindObjectsOfType<TTSVoice>();
		TTSVoice[] array2 = array;
		foreach (TTSVoice val2 in array2)
		{
			if ((Object)(object)val2 != (Object)null && (Object)(object)val2.playerAvatar != (Object)null && val2.voices != null && val2.voices.Length != 0)
			{
				val = val2;
				break;
			}
		}
		if ((Object)(object)val == (Object)null)
		{
			Debug.LogWarning((object)$"[MimicVoice] TTS template scan: {array.Length} TTSVoice object(s) in scene.");
			array2 = array;
			foreach (TTSVoice val3 in array2)
			{
				if ((Object)(object)val3 != (Object)null)
				{
					Debug.LogWarning((object)$"[MimicVoice]   TTSVoice on '{((Object)((Component)val3).gameObject).name}': playerAvatar={(Object)(object)val3.playerAvatar != (Object)null}, voices={((val3.voices != null) ? val3.voices.Length : (-1))}");
				}
			}
			array2 = array;
			foreach (TTSVoice val4 in array2)
			{
				if ((Object)(object)val4 != (Object)null && val4.voices != null && val4.voices.Length != 0)
				{
					val = val4;
					break;
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			Debug.Log((object)"[MimicVoice] TTS template: relaxed match (voices-only, playerAvatar ignored) succeeded.");
		}
		GameObject val5 = Object.Instantiate<GameObject>(((Component)val).gameObject, mimic.transform);
		val5.transform.localPosition = Vector3.up * 1.8f;
		PhotonView[] componentsInChildren = val5.GetComponentsInChildren<PhotonView>(true);
		for (int i = 0; i < componentsInChildren.Length; i++)
		{
			Object.Destroy((Object)(object)componentsInChildren[i]);
		}
		TTSVoice val6 = val5.GetComponent<TTSVoice>();
		if ((Object)(object)val6 == (Object)null)
		{
			val6 = val5.GetComponentInChildren<TTSVoice>(true);
		}
		if ((Object)(object)val6 == (Object)null)
		{
			Object.Destroy((Object)(object)val5);
			return null;
		}
		val6.playerAvatar = null;
		AudioSource component = ((Component)val6).GetComponent<AudioSource>();
		if ((Object)(object)component != (Object)null)
		{
			component.spatialBlend = 1f;
			component.minDistance = 1f;
			component.maxDistance = 20f;
			component.rolloffMode = (AudioRolloffMode)1;
		}
		perMimic[enemyViewId] = val6;
		return val6;
	}
}
[HarmonyPatch(typeof(TTSVoice), "Update")]
internal static class MimicVoice_TTSUpdateGuard
{
	private static bool Prefix(TTSVoice __instance)
	{
		if (!((Object)(object)__instance == (Object)null))
		{
			return (Object)(object)__instance.playerAvatar != (Object)null;
		}
		return true;
	}
}
namespace MimicMonster
{
	[BepInPlugin("jonathan.mimicmonster", "MimicMonster", "1.0.0")]
	public class MimicMonsterPlugin : BaseUnityPlugin
	{
		private void Awake()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			((BaseUnityPlugin)this).Logger.LogInfo((object)"MimicMonster script assembly loaded (EnemyMimic available for bundle deserialization).");
			try
			{
				new Harmony("jonathan.mimicmonster").PatchAll(Assembly.GetExecutingAssembly());
				((BaseUnityPlugin)this).Logger.LogInfo((object)"MimicMonster Harmony patches applied (voice capture + frame feed).");
				SceneManager.sceneLoaded += delegate
				{
					MimicVoiceCapture.VoiceViablePlayers.Clear();
					EnemyMimic.ClearRunStatics();
					MimicTTSPlayback.ClearRunStatics();
				};
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("MimicMonster Harmony PatchAll failed - voice mimicry will be inert: " + ex.Message));
			}
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		internal IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}