Decompiled source of MJStalker v1.8.0

BepInEx/plugins/MJStalker/MJStalker.dll

Decompiled 7 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security.Cryptography;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using TMPro;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.Audio;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.Networking;
using UnityEngine.Rendering;
using UnityEngine.Rendering.HighDefinition;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace MJStalker;

public class MichaelJacksonAI : EnemyAI
{
	private enum Phase
	{
		Approach,
		Reposition,
		Peek
	}

	public const int StRoam = 0;

	public const int StStalk = 1;

	public const int StFlee = 2;

	public const int StChase = 3;

	public const float EyeHeight = 2.35f;

	private const float StartleTime = 0.75f;

	private const float WindupTime = 1.2f;

	private const float MaxLean = 0.74f;

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

	private int mjState;

	private bool peeking;

	private bool relentless;

	private int targetId = -1;

	private int chaseCount;

	private Vector3 leanWorld;

	private float stateStart;

	private float poseUntil;

	private MJAnimator anim;

	private AudioSource voice;

	private AudioSource farVoice;

	private AudioSource music;

	private float musicFade;

	private float eyeGlow;

	private float fearTimer;

	private float lastHitTime;

	private bool refsReady;

	private Phase phase;

	private PlayerControllerB target;

	private AISearchRoutine roamSearch;

	private NavMeshPath planPath;

	private readonly Vector3[] corners = (Vector3[])(object)new Vector3[128];

	private int cornerCount;

	private Vector3 hidePos;

	private Vector3 revealPos;

	private Vector3 faceDir;

	private bool hasPlan;

	private bool planIsPeek;

	private float planTimer;

	private float lostTimer;

	private float peekBlindTimer;

	private float arriveTimer;

	private float watchTimer;

	private float senseTimer;

	private float[] lookTimers = new float[8];

	private float redetectCooldown;

	private float adlibTimer;

	private float holdTimer;

	private float voiceBusyUntil;

	private float fleeTimer;

	private float fleeRepath;

	private Vector3 fleeFrom;

	private int timesFled;

	private int timesCaught;

	private float chaseLostTimer;

	private float heartbeat;

	private int seenCount;

	private PlayerControllerB seenPlayer;

	private int lastAdlib = -1;

	private static readonly FieldInfo CameraUpField = typeof(PlayerControllerB).GetField("cameraUp", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private bool staring;

	private bool moveWasDisabled;

	private bool lookWasDisabled;

	private PlayerControllerB staringPlayer;

	private static float FreezeTime => Mathf.Clamp(Plugin.ChaseFreezeTime.Value, 1.2f, 30f);

	private static float SightRange => Mathf.Clamp(Plugin.SightRange.Value, 10f, 200f);

	public int MjState => mjState;

	public bool Peeking => peeking;

	public bool Relentless => relentless;

	public int TargetId => targetId;

	public int ChaseCount => chaseCount;

	public Vector3 LeanWorld => leanWorld;

	public float StateAge => Time.time - stateStart;

	private int Mask => StartOfRound.Instance.collidersAndRoomMaskAndDefault;

	private PlayerControllerB[] Players => StartOfRound.Instance.allPlayerScripts;

	public static EnemyBehaviourState[] MakeStates()
	{
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Expected O, but got Unknown
		string[] array = new string[4] { "Roaming", "Stalking", "Fleeing", "Chasing" };
		EnemyBehaviourState[] array2 = (EnemyBehaviourState[])(object)new EnemyBehaviourState[array.Length];
		for (int i = 0; i < array.Length; i++)
		{
			array2[i] = new EnemyBehaviourState
			{
				name = array[i]
			};
		}
		return array2;
	}

	private void EnsureRefs()
	{
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Expected O, but got Unknown
		if (refsReady)
		{
			return;
		}
		refsReady = true;
		if ((Object)(object)base.enemyType == (Object)null)
		{
			base.enemyType = MJAssets.Type;
		}
		if (base.enemyBehaviourStates == null || base.enemyBehaviourStates.Length < 4)
		{
			base.enemyBehaviourStates = MakeStates();
		}
		if (base.currentSearch == null)
		{
			base.currentSearch = new AISearchRoutine();
		}
		if ((Object)(object)base.agent == (Object)null)
		{
			base.agent = ((Component)this).GetComponent<NavMeshAgent>();
		}
		if ((Object)(object)base.eye == (Object)null)
		{
			base.eye = ((Component)this).transform.Find("Eye");
		}
		voice = Source("Voice");
		farVoice = Source("FarVoice");
		music = Source("Music");
		if ((Object)(object)base.creatureVoice == (Object)null)
		{
			base.creatureVoice = voice;
		}
		if ((Object)(object)base.creatureSFX == (Object)null)
		{
			base.creatureSFX = Source("SFX");
		}
		anim = ((Component)this).GetComponent<MJAnimator>();
		if ((Object)(object)anim == (Object)null)
		{
			anim = ((Component)this).gameObject.AddComponent<MJAnimator>();
		}
		EnemyAICollisionDetect[] componentsInChildren = ((Component)this).GetComponentsInChildren<EnemyAICollisionDetect>(true);
		foreach (EnemyAICollisionDetect val in componentsInChildren)
		{
			if ((Object)(object)val.mainScript == (Object)null)
			{
				val.mainScript = (EnemyAI)(object)this;
			}
		}
		base.updatePositionThreshold = 0.08f;
		base.enemyHP = Mathf.Max(1, Plugin.Health.Value);
		base.currentBehaviourStateIndex = 0;
		base.currentBehaviourState = base.enemyBehaviourStates[0];
		try
		{
			AudioMixerGroup[] array = SoundManager.Instance.diageticMixer.FindMatchingGroups("Master");
			if (array != null && array.Length != 0)
			{
				AudioSource[] componentsInChildren2 = ((Component)this).GetComponentsInChildren<AudioSource>(true);
				for (int i = 0; i < componentsInChildren2.Length; i++)
				{
					componentsInChildren2[i].outputAudioMixerGroup = array[0];
				}
			}
		}
		catch (Exception)
		{
		}
		if ((Object)(object)music != (Object)null)
		{
			music.maxDistance = Mathf.Max(10f, Plugin.MusicDistance.Value);
		}
	}

	private AudioSource Source(string child)
	{
		Transform val = ((Component)this).transform.Find(child);
		if (!((Object)(object)val != (Object)null))
		{
			return null;
		}
		return ((Component)val).GetComponent<AudioSource>();
	}

	public override void Start()
	{
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Expected O, but got Unknown
		EnsureRefs();
		((EnemyAI)this).Start();
		if (!All.Contains(this))
		{
			All.Add(this);
		}
		stateStart = Time.time;
		MJNet.Register();
		MJSounds.EnsurePlaceholders();
		if (((NetworkBehaviour)this).IsServer)
		{
			roamSearch = new AISearchRoutine();
			roamSearch.randomized = true;
			roamSearch.searchPrecision = 6f;
			EnterRoam(1.5f);
		}
	}

	public override void OnDestroy()
	{
		All.Remove(this);
		ReleaseStare();
		((EnemyAI)this).OnDestroy();
	}

	public override void Update()
	{
		((EnemyAI)this).Update();
		if (!refsReady)
		{
			return;
		}
		float deltaTime = Time.deltaTime;
		UpdateView(deltaTime);
		if (base.isEnemyDead || !((NetworkBehaviour)this).IsServer || !base.ventAnimationFinished || (Object)(object)StartOfRound.Instance == (Object)null || StartOfRound.Instance.allPlayersDead || !((Behaviour)base.agent).enabled)
		{
			return;
		}
		heartbeat -= deltaTime;
		if (heartbeat <= 0f)
		{
			heartbeat = 1f;
			MJNet.SendSync(this);
		}
		if (base.stunNormalizedTimer > 0f)
		{
			base.agent.speed = 0f;
			return;
		}
		switch (mjState)
		{
		case 0:
			UpdateRoam(deltaTime);
			break;
		case 1:
			UpdateStalk(deltaTime);
			break;
		case 2:
			UpdateFlee(deltaTime);
			break;
		case 3:
			UpdateChase(deltaTime);
			break;
		}
	}

	public override void DoAIInterval()
	{
		((EnemyAI)this).DoAIInterval();
		if (base.isEnemyDead || !((NetworkBehaviour)this).IsServer || !refsReady || (Object)(object)StartOfRound.Instance == (Object)null || StartOfRound.Instance.allPlayersDead || base.stunNormalizedTimer > 0f)
		{
			return;
		}
		try
		{
			switch (mjState)
			{
			case 0:
				ThinkRoam();
				break;
			case 1:
				ThinkStalk();
				break;
			case 2:
				ThinkFlee();
				break;
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogError((object)("AI error: " + ex));
		}
	}

	private static Vector3 EyeAt(Vector3 feet)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: 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)
		return feet + Vector3.up * 2.35f;
	}

	private static Vector3 Flat(Vector3 v)
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		v.y = 0f;
		return v;
	}

	private bool Clear(Vector3 from, Vector3 to)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		return !Physics.Linecast(from, to, Mask, (QueryTriggerInteraction)1);
	}

	private bool SeesFrom(Vector3 feet, Vector3 cam)
	{
		//IL_0001: 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)
		return Clear(EyeAt(feet), cam);
	}

	private Vector3 HeadPos()
	{
		//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_0025: Unknown result type (might be due to invalid IL or missing references)
		return EyeAt(((Component)this).transform.position + (peeking ? leanWorld : Vector3.zero));
	}

	private static Vector3 Cam(PlayerControllerB p)
	{
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		return ((Component)p.gameplayCamera).transform.position;
	}

	private void SetState(int s)
	{
		mjState = s;
		stateStart = Time.time;
		if (base.currentBehaviourStateIndex != s)
		{
			((EnemyAI)this).SwitchToBehaviourStateOnLocalClient(s);
		}
		if (Plugin.LogStates.Value)
		{
			Plugin.Log.LogInfo((object)("State -> " + base.enemyBehaviourStates[s].name + (((Object)(object)target != (Object)null) ? (" (target " + target.playerUsername + ")") : "")));
		}
	}

	private void Face(Vector3 dir, float degPerSec, float dt)
	{
		//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_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_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)
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		dir.y = 0f;
		if (!(((Vector3)(ref dir)).sqrMagnitude < 0.0004f))
		{
			Quaternion val = Quaternion.LookRotation(((Vector3)(ref dir)).normalized, Vector3.up);
			((Component)this).transform.rotation = Quaternion.RotateTowards(((Component)this).transform.rotation, val, degPerSec * dt);
		}
	}

	private void StopMoving()
	{
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		base.movingTowardsTargetPlayer = false;
		base.agent.speed = 0f;
		if (((Behaviour)base.agent).enabled && base.agent.isOnNavMesh)
		{
			base.agent.velocity = Vector3.zero;
		}
		base.destination = ((Component)this).transform.position;
	}

	private PlayerControllerB FindVisiblePlayer(float halfFov, float range, float proximity)
	{
		//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_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_0076: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		PlayerControllerB result = null;
		float num = float.MaxValue;
		Vector3 position = base.eye.position;
		PlayerControllerB[] players = Players;
		foreach (PlayerControllerB val in players)
		{
			if (!((Object)(object)val == (Object)null) && ((EnemyAI)this).PlayerIsTargetable(val, false, false, true))
			{
				Vector3 val2 = Cam(val);
				float num2 = Vector3.Distance(position, val2);
				if (!(num2 > range) && (!(num2 > proximity) || !(Vector3.Angle(base.eye.forward, val2 - position) > halfFov)) && Clear(position, val2) && num2 < num)
				{
					num = num2;
					result = val;
				}
			}
		}
		return result;
	}

	private void EnterRoam(float cooldown)
	{
		//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_00a5: Unknown result type (might be due to invalid IL or missing references)
		peeking = false;
		relentless = false;
		target = null;
		targetId = -1;
		leanWorld = Vector3.zero;
		redetectCooldown = cooldown;
		adlibTimer = Random.Range(5f, 12f);
		SetState(0);
		base.agent.updateRotation = true;
		base.agent.autoBraking = true;
		base.agent.angularSpeed = 320f;
		base.agent.speed = Plugin.RoamSpeed.Value;
		base.agent.acceleration = 14f;
		base.movingTowardsTargetPlayer = false;
		((EnemyAI)this).StartSearch(((Component)this).transform.position, roamSearch);
		MJNet.SendSync(this);
	}

	private void UpdateRoam(float dt)
	{
		if (redetectCooldown > 0f)
		{
			redetectCooldown -= dt;
		}
		if (holdTimer > 0f)
		{
			holdTimer -= dt;
			base.agent.speed = 0f;
			return;
		}
		base.agent.speed = Plugin.RoamSpeed.Value;
		adlibTimer -= dt;
		if (adlibTimer <= 0f && Time.time >= voiceBusyUntil)
		{
			int index = NextAdlib(1);
			float num = MJSounds.Length(1, index);
			float num2 = Mathf.Max(2f, Plugin.RoamAdlibMin.Value);
			adlibTimer = num + Random.Range(num2, Mathf.Max(num2 + 1f, Plugin.RoamAdlibMax.Value));
			voiceBusyUntil = Time.time + num + 1f;
			MJNet.SendSfx(this, 1, index, -1);
		}
	}

	private int NextAdlib(int kind)
	{
		int num = Mathf.Max(1, MJSounds.Count(kind));
		int num2 = Random.Range(0, num);
		if (num > 1 && num2 == lastAdlib)
		{
			num2 = (num2 + 1) % num;
		}
		lastAdlib = num2;
		return num2;
	}

	private void ThinkRoam()
	{
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		if (holdTimer > 0f)
		{
			return;
		}
		if (base.currentSearch == null || !base.currentSearch.inProgress)
		{
			((EnemyAI)this).StartSearch(((Component)this).transform.position, roamSearch);
		}
		if (!(redetectCooldown > 0f))
		{
			PlayerControllerB val = FindVisiblePlayer(80f, SightRange, 5f);
			if ((Object)(object)val != (Object)null)
			{
				EnterStalk(val);
			}
		}
	}

	private void EnterStalk(PlayerControllerB p)
	{
		//IL_0078: Unknown result type (might be due to invalid IL or missing references)
		//IL_007d: Unknown result type (might be due to invalid IL or missing references)
		((EnemyAI)this).StopSearch(base.currentSearch, true);
		target = p;
		targetId = (int)p.playerClientId;
		phase = Phase.Approach;
		hasPlan = false;
		planTimer = 0f;
		lostTimer = 0f;
		watchTimer = 0f;
		for (int i = 0; i < lookTimers.Length; i++)
		{
			lookTimers[i] = 0f;
		}
		peeking = false;
		leanWorld = Vector3.zero;
		SetState(1);
		base.agent.updateRotation = true;
		base.agent.autoBraking = true;
		base.agent.acceleration = 26f;
		base.movingTowardsTargetPlayer = false;
		MJNet.SendSync(this);
	}

	private void StartPeek()
	{
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_008b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0091: Unknown result type (might be due to invalid IL or missing references)
		//IL_0082: 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_00a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00da: 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)
		phase = Phase.Peek;
		peeking = true;
		peekBlindTimer = 0f;
		StopMoving();
		base.agent.updateRotation = false;
		Vector3 val = Flat(revealPos - ((Component)this).transform.position);
		float num = Mathf.Min(0.74f, ((Vector3)(ref val)).magnitude + Mathf.Clamp(Plugin.PeekOvershoot.Value, 0f, 0.74f));
		leanWorld = ((((Vector3)(ref val)).sqrMagnitude > 0.0025f) ? (((Vector3)(ref val)).normalized * num) : Vector3.zero);
		faceDir = Flat(((Component)target).transform.position - revealPos);
		if (((Vector3)(ref faceDir)).sqrMagnitude < 0.01f)
		{
			faceDir = ((Component)this).transform.forward;
		}
		MJNet.SendSync(this);
	}

	private void StopPeek()
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		if (peeking)
		{
			peeking = false;
			leanWorld = Vector3.zero;
			base.agent.updateRotation = true;
			MJNet.SendSync(this);
		}
	}

	private void UpdateStalk(float dt)
	{
		//IL_0024: 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_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: 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_009b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00aa: 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_00b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0177: Unknown result type (might be due to invalid IL or missing references)
		//IL_017c: Unknown result type (might be due to invalid IL or missing references)
		//IL_017e: Unknown result type (might be due to invalid IL or missing references)
		//IL_017f: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a2: 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_01e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_0202: Unknown result type (might be due to invalid IL or missing references)
		//IL_0281: 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_0287: Unknown result type (might be due to invalid IL or missing references)
		//IL_0289: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)target == (Object)null)
		{
			return;
		}
		if (phase == Phase.Peek)
		{
			faceDir = Flat(((Component)target).transform.position - (((Component)this).transform.position + leanWorld));
			Face(faceDir, 240f, dt);
		}
		senseTimer += dt;
		if (senseTimer < 0.08f)
		{
			return;
		}
		float num = senseTimer;
		senseTimer = 0f;
		Vector3 val = HeadPos();
		Vector3 val2 = ((Component)this).transform.position + Vector3.up * 1.5f;
		seenCount = 0;
		seenPlayer = null;
		PlayerControllerB val3 = null;
		PlayerControllerB val4 = null;
		bool flag = false;
		float num2 = -1f;
		float value = Plugin.SpotAngle.Value;
		float sightRange = SightRange;
		int num3 = (int)Mathf.Clamp(Plugin.SpotDistance.Value, 2f, 200f);
		float num4 = Mathf.Max(0.05f, Plugin.SpotHoldTime.Value);
		PlayerControllerB[] players = Players;
		if (lookTimers.Length < players.Length)
		{
			lookTimers = new float[players.Length];
		}
		for (int i = 0; i < players.Length; i++)
		{
			PlayerControllerB val5 = players[i];
			if ((Object)(object)val5 == (Object)null || !((EnemyAI)this).PlayerIsTargetable(val5, false, false, true))
			{
				lookTimers[i] = 0f;
				continue;
			}
			Vector3 val6 = Cam(val5);
			float num5 = Vector3.Distance(val, val6);
			if (num5 > sightRange)
			{
				lookTimers[i] = 0f;
				continue;
			}
			bool num6 = Clear(val, val6);
			if (num6)
			{
				seenCount++;
				if ((Object)(object)seenPlayer == (Object)null || (Object)(object)val5 == (Object)(object)target)
				{
					seenPlayer = val5;
				}
			}
			bool flag2 = val5.HasLineOfSightToPosition(val, value, num3, -1f, -1);
			if (!flag2 && !peeking)
			{
				flag2 = val5.HasLineOfSightToPosition(val2, value, num3, -1f, -1);
			}
			if (flag2)
			{
				flag = true;
				lookTimers[i] += num;
				if (lookTimers[i] >= num4 && (Object)(object)val3 == (Object)null)
				{
					val3 = val5;
				}
			}
			else
			{
				lookTimers[i] = Mathf.Max(0f, lookTimers[i] - num * 3f);
			}
			if (num6 && num5 <= (float)num3)
			{
				float num7 = Vector3.Angle(((Component)val5.gameplayCamera).transform.forward, val - val6);
				if ((Object)(object)val5 == (Object)(object)target)
				{
					num7 += 10f;
				}
				if (num7 > num2)
				{
					num2 = num7;
					val4 = val5;
				}
			}
		}
		if ((Object)(object)val3 != (Object)null)
		{
			GetSpotted(val3);
		}
		else if ((Object)(object)val4 != (Object)null && !flag)
		{
			watchTimer += num;
			if (watchTimer >= CurrentChaseDelay())
			{
				EnterChase(val4);
			}
		}
	}

	private float CurrentChaseDelay()
	{
		float num = Plugin.ChaseDelay.Value - Mathf.Max(0f, Plugin.ChaseDelayStep.Value) * (float)Mathf.Max(0, timesCaught - 1);
		return Mathf.Max(Mathf.Max(0f, Plugin.ChaseDelayMinimum.Value), num);
	}

	private void ThinkStalk()
	{
		//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_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_00c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_018d: Unknown result type (might be due to invalid IL or missing references)
		//IL_018e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d6: 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_0206: Unknown result type (might be due to invalid IL or missing references)
		//IL_020c: 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_01aa: 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_01b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_0100: Unknown result type (might be due to invalid IL or missing references)
		//IL_0105: Unknown result type (might be due to invalid IL or missing references)
		//IL_0225: Unknown result type (might be due to invalid IL or missing references)
		//IL_022a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0315: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)target == (Object)null || !((EnemyAI)this).PlayerIsTargetable(target, false, false, true))
		{
			PlayerControllerB val = FindVisiblePlayer(180f, Mathf.Min(SightRange, 45f), 35f);
			if ((Object)(object)val == (Object)null)
			{
				StopPeek();
				EnterRoam(2f);
				return;
			}
			target = val;
			targetId = (int)val.playerClientId;
			StopPeek();
			phase = Phase.Approach;
			hasPlan = false;
			planTimer = 0f;
			MJNet.SendSync(this);
		}
		Vector3 val2 = Cam(target);
		Vector3 position = ((Component)target).transform.position;
		if (phase == Phase.Peek)
		{
			bool num = SeesFrom(((Component)this).transform.position, val2) && SeesFrom(hidePos, val2);
			bool flag = Vector3.Distance(((Component)this).transform.position, position) < 2.4f;
			if (Clear(HeadPos(), val2))
			{
				peekBlindTimer = 0f;
			}
			else
			{
				peekBlindTimer += base.AIIntervalTime;
			}
			if (!(num || flag) && !(peekBlindTimer > 1.2f))
			{
				return;
			}
			StopPeek();
			phase = Phase.Approach;
			hasPlan = false;
			planTimer = 0f;
		}
		planTimer -= base.AIIntervalTime;
		if (planTimer <= 0f)
		{
			planTimer = 0.6f;
			Replan(val2, position);
		}
		if (!hasPlan)
		{
			StopMoving();
			Face(Flat(position - ((Component)this).transform.position), 400f, base.AIIntervalTime);
			lostTimer += base.AIIntervalTime;
			if (lostTimer > 7f)
			{
				EnterRoam(3f);
			}
			return;
		}
		lostTimer = 0f;
		float num2 = Vector3.Distance(((Component)this).transform.position, hidePos);
		int num3;
		if (num2 < 0.6f)
		{
			Vector3 velocity = base.agent.velocity;
			num3 = ((((Vector3)(ref velocity)).sqrMagnitude < 0.04f) ? 1 : 0);
		}
		else
		{
			num3 = 0;
		}
		bool flag2 = (byte)num3 != 0;
		arriveTimer = (flag2 ? (arriveTimer + base.AIIntervalTime) : 0f);
		if (num2 < ((phase == Phase.Reposition) ? 0.6f : 0.15f) || arriveTimer > 0.5f)
		{
			arriveTimer = 0f;
			if (phase == Phase.Reposition)
			{
				phase = Phase.Approach;
				planTimer = 0f;
				StopMoving();
			}
			else if (planIsPeek)
			{
				StartPeek();
			}
			else
			{
				StopMoving();
			}
		}
		else
		{
			float value = Plugin.StalkSpeed.Value;
			base.agent.speed = ((phase == Phase.Reposition) ? (value * 1.25f) : ((num2 > 12f) ? (value * 1.3f) : ((num2 > 3f) ? value : (value * 0.6f))));
			((EnemyAI)this).SetDestinationToPosition(hidePos, false);
		}
	}

	private void Replan(Vector3 cam, Vector3 feet)
	{
		//IL_0001: 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_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: 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_0068: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: 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_002c: Unknown result type (might be due to invalid IL or missing references)
		if (!PlanPeek(cam, feet, out var hide, out var reveal, out var startVisible, out var _))
		{
			hasPlan = false;
			return;
		}
		if (startVisible)
		{
			if (FindCover(cam, feet, out var cover))
			{
				hidePos = cover;
				planIsPeek = false;
				hasPlan = true;
				phase = Phase.Reposition;
			}
			else
			{
				hasPlan = false;
			}
			return;
		}
		if (phase == Phase.Reposition)
		{
			phase = Phase.Approach;
		}
		hidePos = hide;
		revealPos = reveal;
		planIsPeek = Vector3.Distance(reveal, feet) >= 3f;
		hasPlan = true;
	}

	private bool BuildPath(Vector3 goal)
	{
		//IL_003b: 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_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_0062: 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_0036: Expected O, but got Unknown
		//IL_0078: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Invalid comparison between Unknown and I4
		cornerCount = 0;
		if (!((Behaviour)base.agent).enabled || !base.agent.isOnNavMesh)
		{
			return false;
		}
		if (planPath == null)
		{
			planPath = new NavMeshPath();
		}
		Vector3 navMeshPosition = RoundManager.Instance.GetNavMeshPosition(goal, RoundManager.Instance.navHit, 2.7f, base.agent.areaMask);
		if (!base.agent.CalculatePath(navMeshPosition, planPath))
		{
			return false;
		}
		if ((int)planPath.status == 2)
		{
			return false;
		}
		cornerCount = planPath.GetCornersNonAlloc(corners);
		return cornerCount >= 1;
	}

	private float PathLength()
	{
		//IL_0014: 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)
		float num = 0f;
		for (int i = 1; i < cornerCount; i++)
		{
			num += Vector3.Distance(corners[i - 1], corners[i]);
		}
		return num;
	}

	private Vector3 PointAt(float s)
	{
		//IL_000e: 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)
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a3: 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_0066: 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)
		if (cornerCount == 0)
		{
			return ((Component)this).transform.position;
		}
		if (s <= 0f)
		{
			return corners[0];
		}
		for (int i = 1; i < cornerCount; i++)
		{
			float num = Vector3.Distance(corners[i - 1], corners[i]);
			if (s <= num)
			{
				return Vector3.Lerp(corners[i - 1], corners[i], (num < 0.0001f) ? 0f : (s / num));
			}
			s -= num;
		}
		return corners[cornerCount - 1];
	}

	private bool PlanPeek(Vector3 cam, Vector3 feet, out Vector3 hide, out Vector3 reveal, out bool startVisible, out float revealToEnd)
	{
		//IL_0009: 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_000f: 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_0015: 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_0028: 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_003f: 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_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_008b: Unknown result type (might be due to invalid IL or missing references)
		//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_00da: 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_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_017a: Unknown result type (might be due to invalid IL or missing references)
		//IL_017f: 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_0170: 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_0150: Unknown result type (might be due to invalid IL or missing references)
		hide = (reveal = ((Component)this).transform.position);
		startVisible = false;
		revealToEnd = 0f;
		if (!BuildPath(feet))
		{
			return false;
		}
		if (SeesFrom(corners[0], cam) || SeesFrom(((Component)this).transform.position, cam))
		{
			startVisible = true;
			return true;
		}
		float num = PathLength();
		float num2 = 0f;
		for (float num3 = 0.5f; num3 <= num + 0.5f; num3 += 0.5f)
		{
			float num4 = Mathf.Min(num3, num);
			if (SeesFrom(PointAt(num4), cam))
			{
				float num5 = num2;
				float num6 = num4;
				for (int i = 0; i < 4; i++)
				{
					float num7 = (num5 + num6) * 0.5f;
					if (SeesFrom(PointAt(num7), cam))
					{
						num6 = num7;
					}
					else
					{
						num5 = num7;
					}
				}
				reveal = PointAt(num6);
				float num8 = Mathf.Max(0.3f, 0.74f - Mathf.Clamp(Plugin.PeekOvershoot.Value, 0f, 0.74f));
				float num9 = Mathf.Max(0f, num6 - num8);
				hide = PointAt(num9);
				for (int j = 0; j < 4; j++)
				{
					if (!(num9 > 0f))
					{
						break;
					}
					if (!SeesFrom(hide, cam))
					{
						break;
					}
					num9 = Mathf.Max(0f, num9 - 0.4f);
					hide = PointAt(num9);
				}
				if (SeesFrom(hide, cam))
				{
					startVisible = true;
					return true;
				}
				revealToEnd = num - num6;
				return true;
			}
			num2 = num4;
			if (num4 >= num)
			{
				break;
			}
		}
		return false;
	}

	private bool FindCover(Vector3 cam, Vector3 feet, out Vector3 cover)
	{
		//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_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: 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_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_0076: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_009b: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_014a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0154: Expected O, but got Unknown
		//IL_00b7: 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_00c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00da: Unknown result type (might be due to invalid IL or missing references)
		//IL_016e: 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_01be: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0212: Unknown result type (might be due to invalid IL or missing references)
		//IL_0217: Unknown result type (might be due to invalid IL or missing references)
		cover = ((Component)this).transform.position;
		Vector3 position = ((Component)this).transform.position;
		List<KeyValuePair<float, Vector3>> list = new List<KeyValuePair<float, Vector3>>();
		float[] array = new float[4] { 3f, 6f, 10f, 15f };
		NavMeshHit val = default(NavMeshHit);
		foreach (float num in array)
		{
			for (int j = 0; j < 360; j += 30)
			{
				float num2 = (float)j * ((float)Math.PI / 180f);
				if (NavMesh.SamplePosition(position + new Vector3(Mathf.Cos(num2), 0f, Mathf.Sin(num2)) * num, ref val, 2f, base.agent.areaMask))
				{
					Vector3 position2 = ((NavMeshHit)(ref val)).position;
					if (!(Mathf.Abs(position2.y - position.y) > 4f) && !(Vector3.Distance(position2, feet) < 5f) && !SeesFrom(position2, cam))
					{
						list.Add(new KeyValuePair<float, Vector3>(Vector3.Distance(position, position2), position2));
					}
				}
			}
			if (list.Count >= 4)
			{
				break;
			}
		}
		if (list.Count == 0)
		{
			return false;
		}
		list.Sort((KeyValuePair<float, Vector3> x, KeyValuePair<float, Vector3> y) => x.Key.CompareTo(y.Key));
		if (planPath == null)
		{
			planPath = new NavMeshPath();
		}
		for (int num3 = 0; num3 < list.Count && num3 < 5; num3++)
		{
			if (base.agent.CalculatePath(list[num3].Value, planPath) && (int)planPath.status == 0)
			{
				int cornersNonAlloc = planPath.GetCornersNonAlloc(corners);
				float num4 = 0f;
				for (int num5 = 1; num5 < cornersNonAlloc; num5++)
				{
					num4 += Vector3.Distance(corners[num5 - 1], corners[num5]);
				}
				if (!(num4 > list[num3].Key * 2.5f + 4f))
				{
					cover = list[num3].Value;
					return true;
				}
			}
		}
		return false;
	}

	private void GetSpotted(PlayerControllerB by)
	{
		//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_0207: Unknown result type (might be due to invalid IL or missing references)
		//IL_0208: Unknown result type (might be due to invalid IL or missing references)
		//IL_0222: Unknown result type (might be due to invalid IL or missing references)
		//IL_0227: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_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 (mjState == 2 || mjState == 3)
		{
			return;
		}
		if (mjState == 1)
		{
			timesCaught++;
			if (Plugin.LogStates.Value)
			{
				Plugin.Log.LogInfo((object)("Caught stalking " + timesCaught + " time(s); he now attacks after " + CurrentChaseDelay().ToString("0.#") + " s unnoticed."));
			}
		}
		int value = Plugin.Nerve.Value;
		if (value >= 0 && timesFled >= value)
		{
			PlayerControllerB val = (((Object)(object)by != (Object)null && ((EnemyAI)this).PlayerIsTargetable(by, false, false, true)) ? by : (((Object)(object)target != (Object)null && ((EnemyAI)this).PlayerIsTargetable(target, false, false, true)) ? target : FindVisiblePlayer(180f, SightRange, 35f)));
			if ((Object)(object)val != (Object)null)
			{
				if (Plugin.LogStates.Value)
				{
					Plugin.Log.LogInfo((object)("Caught, but he is out of nerve: chasing " + val.playerUsername + "."));
				}
				holdTimer = 0f;
				base.agent.updateRotation = true;
				EnterChase(val);
				return;
			}
		}
		timesFled++;
		if (Plugin.LogStates.Value && value >= 0)
		{
			Plugin.Log.LogInfo((object)("Scared off " + timesFled + " of " + value + " times."));
		}
		Vector3 val2 = (((Object)(object)by != (Object)null) ? ((Component)by).transform.position : (((Object)(object)target != (Object)null) ? ((Component)target).transform.position : (((Component)this).transform.position + ((Component)this).transform.forward)));
		fleeFrom = val2;
		((EnemyAI)this).StopSearch(base.currentSearch, true);
		peeking = false;
		leanWorld = Vector3.zero;
		fleeTimer = Plugin.FleeDuration.Value;
		fleeRepath = 0f;
		SetState(2);
		StopMoving();
		base.agent.updateRotation = false;
		base.agent.autoBraking = false;
		base.agent.acceleration = 30f;
		MJNet.SendSync(this);
		int index = NextAdlib(0);
		voiceBusyUntil = Time.time + MJSounds.Length(0, index) + 2f;
		MJNet.SendSfx(this, 0, index, ((Object)(object)by != (Object)null) ? ((int)by.playerClientId) : (-1));
	}

	private void UpdateFlee(float dt)
	{
		//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_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: 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_008a: Unknown result type (might be due to invalid IL or missing references)
		fleeTimer -= dt;
		if (StateAge < 0.75f)
		{
			base.agent.speed = 0f;
			Face(Flat(fleeFrom - ((Component)this).transform.position), 720f, dt);
		}
		else
		{
			base.agent.speed = Plugin.FleeSpeed.Value;
			Vector3 val = Flat(base.agent.velocity);
			if (((Vector3)(ref val)).sqrMagnitude > 0.25f)
			{
				Face(-val, 540f, dt);
			}
		}
		if (fleeTimer <= 0f)
		{
			base.agent.updateRotation = true;
			EnterRoam(3f);
		}
	}

	private void ThinkFlee()
	{
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		if (StateAge < 0.375f)
		{
			return;
		}
		fleeRepath -= base.AIIntervalTime;
		bool flag = Vector3.Distance(((Component)this).transform.position, base.destination) < 2f;
		if (fleeRepath <= 0f || flag)
		{
			fleeRepath = 2.5f;
			if (PickFleeDestination(out var dest))
			{
				((EnemyAI)this).SetDestinationToPosition(dest, false);
			}
		}
	}

	private bool PickFleeDestination(out Vector3 dest)
	{
		//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_002a: 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_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00aa: 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_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cf: 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_00eb: 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_00ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f2: 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_011a: 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_011f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0152: Unknown result type (might be due to invalid IL or missing references)
		//IL_0157: Unknown result type (might be due to invalid IL or missing references)
		//IL_0159: Unknown result type (might be due to invalid IL or missing references)
		//IL_015a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0262: Unknown result type (might be due to invalid IL or missing references)
		//IL_0263: Unknown result type (might be due to invalid IL or missing references)
		//IL_0258: Unknown result type (might be due to invalid IL or missing references)
		//IL_0262: Expected O, but got Unknown
		//IL_0182: Unknown result type (might be due to invalid IL or missing references)
		//IL_0187: 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_018d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0361: Unknown result type (might be due to invalid IL or missing references)
		//IL_0366: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b4: 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_01b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c1: 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)
		//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_0201: Unknown result type (might be due to invalid IL or missing references)
		//IL_029d: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_032f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0334: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_02fd: Unknown result type (might be due to invalid IL or missing references)
		//IL_030f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0314: Unknown result type (might be due to invalid IL or missing references)
		dest = ((Component)this).transform.position;
		if (base.allAINodes == null || base.allAINodes.Length == 0)
		{
			return false;
		}
		Vector3 position = ((Component)this).transform.position;
		List<Vector3> list = new List<Vector3>();
		PlayerControllerB[] players = Players;
		foreach (PlayerControllerB val in players)
		{
			if ((Object)(object)val != (Object)null && val.isPlayerControlled && !val.isPlayerDead && val.isInsideFactory)
			{
				list.Add(((Component)val).transform.position);
			}
		}
		if (list.Count == 0)
		{
			list.Add(fleeFrom);
		}
		Vector3 val2 = list[0];
		foreach (Vector3 item in list)
		{
			if (Vector3.Distance(position, item) < Vector3.Distance(position, val2))
			{
				val2 = item;
			}
		}
		Vector3 val3 = Flat(position - val2);
		val3 = ((((Vector3)(ref val3)).sqrMagnitude > 0.01f) ? ((Vector3)(ref val3)).normalized : (-((Component)this).transform.forward));
		List<KeyValuePair<float, Vector3>> list2 = new List<KeyValuePair<float, Vector3>>();
		GameObject[] allAINodes = base.allAINodes;
		foreach (GameObject val4 in allAINodes)
		{
			if ((Object)(object)val4 == (Object)null)
			{
				continue;
			}
			Vector3 position2 = val4.transform.position;
			float num = Vector3.Distance(position, position2);
			if (num < 7f)
			{
				continue;
			}
			float num2 = float.MaxValue;
			foreach (Vector3 item2 in list)
			{
				num2 = Mathf.Min(num2, Vector3.Distance(position2, item2));
			}
			Vector3 val5 = Flat(position2 - position);
			float num3 = Vector3.Dot(((Vector3)(ref val5)).normalized, val3);
			float key = Mathf.Min(num2, 60f) + 14f * num3 - Mathf.Abs(num - 35f) * 0.2f;
			list2.Add(new KeyValuePair<float, Vector3>(key, position2));
		}
		if (list2.Count == 0)
		{
			return false;
		}
		list2.Sort((KeyValuePair<float, Vector3> x, KeyValuePair<float, Vector3> y) => y.Key.CompareTo(x.Key));
		if (planPath == null)
		{
			planPath = new NavMeshPath();
		}
		bool flag = Vector3.Distance(position, val2) < 18f;
		for (int num4 = 0; num4 < list2.Count && num4 < 8 && base.agent.isOnNavMesh; num4++)
		{
			if (!base.agent.CalculatePath(list2[num4].Value, planPath) || (int)planPath.status != 0)
			{
				continue;
			}
			if (planPath.GetCornersNonAlloc(corners) >= 2 && flag)
			{
				Vector3 val6 = Flat(corners[1] - corners[0]);
				if (((Vector3)(ref val6)).sqrMagnitude > 0.04f && Vector3.Dot(((Vector3)(ref val6)).normalized, val3) < -0.25f)
				{
					continue;
				}
			}
			dest = list2[num4].Value;
			return true;
		}
		dest = list2[0].Value;
		return true;
	}

	private void EnterChase(PlayerControllerB p)
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		((EnemyAI)this).StopSearch(base.currentSearch, true);
		peeking = false;
		leanWorld = Vector3.zero;
		chaseCount++;
		relentless = false;
		chaseLostTimer = 0f;
		target = p;
		targetId = (int)p.playerClientId;
		SetState(3);
		base.agent.updateRotation = true;
		base.agent.autoBraking = false;
		base.agent.acceleration = 60f;
		base.agent.angularSpeed = 600f;
		base.agent.speed = 0f;
		((EnemyAI)this).SetMovingTowardsTargetPlayer(p);
		MJNet.SendSync(this);
	}

	private static float SpeedFactor(float age)
	{
		float[] chaseSpeedPoints = Plugin.ChaseSpeedPoints;
		int num = chaseSpeedPoints.Length / 2;
		if (num == 0)
		{
			return 1f;
		}
		if (age <= chaseSpeedPoints[0])
		{
			return chaseSpeedPoints[1];
		}
		for (int i = 1; i < num; i++)
		{
			float num2 = chaseSpeedPoints[(i - 1) * 2];
			float num3 = chaseSpeedPoints[i * 2];
			if (age <= num3)
			{
				return Mathf.Lerp(chaseSpeedPoints[(i - 1) * 2 + 1], chaseSpeedPoints[i * 2 + 1], (num3 - num2 < 0.001f) ? 1f : ((age - num2) / (num3 - num2)));
			}
		}
		return chaseSpeedPoints[(num - 1) * 2 + 1];
	}

	private float ChaseSpeed(float age)
	{
		float num = (((Object)(object)target != (Object)null) ? target.movementSpeed : 4.6f);
		if (num < 1f || num > 20f)
		{
			num = 4.6f;
		}
		return num * SpeedFactor(age);
	}

	private void UpdateChase(float dt)
	{
		//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_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_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_0163: Unknown result type (might be due to invalid IL or missing references)
		//IL_016e: 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_0178: 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)
		bool flag = (Object)(object)target == (Object)null || target.isPlayerDead;
		bool flag2 = !flag && MJShow.IsTaken(target);
		if (flag || flag2 || !target.isPlayerControlled || !target.isInsideFactory)
		{
			EndChase((flag || flag2) && (Object)(object)target != (Object)null);
			return;
		}
		float stateAge = StateAge;
		Vector3 val = Cam(target);
		bool num = Vector3.Distance(base.eye.position, val) < 120f && Clear(base.eye.position, val);
		float freezeTime = FreezeTime;
		if (num || stateAge < freezeTime)
		{
			chaseLostTimer = 0f;
		}
		else
		{
			chaseLostTimer += dt;
		}
		float num2 = Mathf.Max(1f, Plugin.ChaseLoseSight.Value + Mathf.Max(0f, Plugin.ChaseLoseSightStep.Value) * (float)Mathf.Max(0, chaseCount - 1));
		if (chaseLostTimer >= num2)
		{
			EndChase(killed: false);
		}
		else if (stateAge < freezeTime)
		{
			base.agent.speed = 0f;
			if (base.agent.isOnNavMesh)
			{
				base.agent.velocity = Vector3.zero;
			}
			Face(Flat(((Component)target).transform.position - ((Component)this).transform.position), 300f, dt);
		}
		else
		{
			base.agent.speed = ChaseSpeed(stateAge);
			if (!base.movingTowardsTargetPlayer)
			{
				((EnemyAI)this).SetMovingTowardsTargetPlayer(target);
			}
		}
	}

	private void EndChase(bool killed)
	{
		base.movingTowardsTargetPlayer = false;
		if (killed)
		{
			holdTimer = 2f;
			int index = NextAdlib(0);
			voiceBusyUntil = Time.time + MJSounds.Length(0, index) + 2f;
			MJNet.SendSfx(this, 2, index, -1);
		}
		EnterRoam(killed ? 4f : 6f);
	}

	public override void OnCollideWithPlayer(Collider other)
	{
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_0084: Unknown result type (might be due to invalid IL or missing references)
		//IL_008e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0093: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_00a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00da: 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)
		((EnemyAI)this).OnCollideWithPlayer(other);
		if (mjState != 3 || StateAge < FreezeTime || Time.time - lastHitTime < 1f)
		{
			return;
		}
		PlayerControllerB val = ((EnemyAI)this).MeetsStandardPlayerCollisionConditions(other, false, false);
		if ((Object)(object)val == (Object)null)
		{
			return;
		}
		lastHitTime = Time.time;
		int value = Plugin.ContactDamage.Value;
		if (value <= 0)
		{
			return;
		}
		Vector3 val2 = Flat(((Component)val).transform.position - ((Component)this).transform.position);
		Vector3 val3 = ((Vector3)(ref val2)).normalized * 5f + Vector3.up * 2f;
		if ((value < 100 && val.health - value > 0) || !Plugin.StageShow.Value || !MJShow.Begin(val, val3))
		{
			if (value >= 100)
			{
				val2 = default(Vector3);
				val.KillPlayer(val3, true, (CauseOfDeath)6, 0, val2, false);
			}
			else
			{
				val2 = default(Vector3);
				val.DamagePlayer(value, true, true, (CauseOfDeath)6, 0, false, val2);
			}
		}
	}

	public override void HitEnemy(int force = 1, PlayerControllerB playerWhoHit = null, bool playHitSFX = false, int hitID = -1)
	{
		((EnemyAI)this).HitEnemy(force, playerWhoHit, playHitSFX, hitID);
		if (base.isEnemyDead || !refsReady)
		{
			return;
		}
		base.enemyHP -= Mathf.Max(1, force);
		if (base.enemyHP <= 0)
		{
			if (((NetworkBehaviour)this).IsOwner)
			{
				((EnemyAI)this).KillEnemyOnOwnerClient(false);
			}
		}
		else if (mjState == 2 || mjState == 3)
		{
			AudioClip val = MJSounds.Short(base.enemyHP);
			if ((Object)(object)val != (Object)null && (Object)(object)voice != (Object)null)
			{
				voice.PlayOneShot(val, 0.7f * Mathf.Clamp01(Plugin.VoiceVolume.Value));
			}
		}
		else if (((NetworkBehaviour)this).IsServer)
		{
			holdTimer = 0f;
			GetSpotted(playerWhoHit);
		}
	}

	public override void KillEnemy(bool destroy = false)
	{
		//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)
		if (!destroy && refsReady && !base.isEnemyDead)
		{
			MJSounds.EnsurePlaceholders();
			base.dieSFX = MJSounds.Short(3);
			if ((Object)(object)voice != (Object)null)
			{
				voice.pitch = 0.72f;
			}
		}
		((EnemyAI)this).KillEnemy(destroy);
		if (destroy || !base.isEnemyDead)
		{
			return;
		}
		peeking = false;
		leanWorld = Vector3.zero;
		targetId = -1;
		base.movingTowardsTargetPlayer = false;
		if (((NetworkBehaviour)this).IsServer)
		{
			try
			{
				((EnemyAI)this).StopSearch(base.currentSearch, true);
			}
			catch (Exception)
			{
			}
		}
		if (Plugin.LogStates.Value)
		{
			Plugin.Log.LogInfo((object)"He is dead.");
		}
	}

	internal void ApplySync(int state, bool isPeeking, bool isRelentless, int target, int chases, Vector3 lean, float stateAge)
	{
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		if (!refsReady)
		{
			EnsureRefs();
		}
		if (state < 0 || state > 3)
		{
			return;
		}
		peeking = isPeeking;
		relentless = isRelentless;
		targetId = target;
		chaseCount = chases;
		leanWorld = lean;
		if (state != mjState)
		{
			mjState = state;
			stateStart = Time.time - Mathf.Max(0f, stateAge);
			if (base.currentBehaviourStateIndex != state)
			{
				((EnemyAI)this).SwitchToBehaviourStateOnLocalClient(state);
			}
		}
	}

	internal void PlaySfxLocal(int kind, int index, int playerId)
	{
		//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
		if (!refsReady)
		{
			EnsureRefs();
		}
		MJSounds.EnsurePlaceholders();
		float num = Mathf.Clamp01(Plugin.VoiceVolume.Value);
		AudioClip val = MJSounds.Get((kind == 1) ? 1 : 0, index);
		PlayerControllerB val2 = (((Object)(object)GameNetworkManager.Instance != (Object)null) ? GameNetworkManager.Instance.localPlayerController : null);
		if (kind == 1)
		{
			if ((Object)(object)val != (Object)null && (Object)(object)farVoice != (Object)null)
			{
				farVoice.PlayOneShot(val, num);
			}
			return;
		}
		if ((Object)(object)val != (Object)null && (Object)(object)voice != (Object)null)
		{
			voice.PlayOneShot(val, num);
		}
		if (kind == 2)
		{
			poseUntil = Time.time + 2f;
			if ((Object)(object)anim != (Object)null)
			{
				anim.Retrigger();
			}
		}
		else if ((Object)(object)val2 != (Object)null && !val2.isPlayerDead && val2.isPlayerControlled && ((int)val2.playerClientId == playerId || val2.HasLineOfSightToPosition(HeadPos(), 70f, 50, -1f, -1)))
		{
			val2.JumpToFearLevel(1f, true);
			try
			{
				HUDManager.Instance.ShakeCamera((ScreenShakeType)0);
			}
			catch (Exception)
			{
			}
		}
	}

	private PlayerControllerB TargetPlayer()
	{
		if (targetId < 0 || (Object)(object)StartOfRound.Instance == (Object)null)
		{
			return null;
		}
		PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
		if (targetId >= allPlayerScripts.Length)
		{
			return null;
		}
		return allPlayerScripts[targetId];
	}

	private void UpdateView(float dt)
	{
		//IL_00bc: 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_00c1: 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_021d: Unknown result type (might be due to invalid IL or missing references)
		//IL_025d: Unknown result type (might be due to invalid IL or missing references)
		float stateAge = StateAge;
		Anim mode = (base.isEnemyDead ? Anim.Dead : ((base.stunNormalizedTimer > 0f) ? Anim.Stunned : ((Time.time < poseUntil) ? Anim.Startle : (mjState switch
		{
			1 => peeking ? Anim.Peek : Anim.Sneak, 
			2 => (stateAge < 0.75f) ? Anim.Startle : Anim.Moonwalk, 
			3 => (stateAge < 1.2f) ? Anim.Windup : Anim.Dance, 
			_ => Anim.Walk, 
		}))));
		PlayerControllerB val = TargetPlayer();
		if ((Object)(object)anim != (Object)null)
		{
			anim.SetMode(mode);
			anim.leanWorld = (peeking ? leanWorld : Vector3.zero);
			anim.lookTarget = ((!base.isEnemyDead && (Object)(object)val != (Object)null && (mjState == 1 || mjState == 3)) ? ((Component)val.gameplayCamera).transform : null);
			float num = ((!base.isEnemyDead && mjState == 1) ? 1f : 0f);
			eyeGlow = Mathf.MoveTowards(eyeGlow, num, dt * ((num > eyeGlow) ? 2.5f : 4f));
			anim.SetEyeGlow(eyeGlow * Mathf.Max(0f, Plugin.EyeGlow.Value));
		}
		UpdateMusic(dt, stateAge);
		UpdateStare(dt);
		if (base.isEnemyDead || mjState != 3)
		{
			return;
		}
		fearTimer -= dt;
		if (!(fearTimer <= 0f))
		{
			return;
		}
		fearTimer = 0.5f;
		PlayerControllerB val2 = (((Object)(object)GameNetworkManager.Instance != (Object)null) ? GameNetworkManager.Instance.localPlayerController : null);
		if ((Object)(object)val2 != (Object)null && !val2.isPlayerDead && val2.isPlayerControlled && val2.isInsideFactory)
		{
			float num2 = Vector3.Distance(((Component)val2).transform.position, ((Component)this).transform.position);
			if ((Object)(object)val == (Object)(object)val2)
			{
				val2.JumpToFearLevel((num2 < 12f) ? 1f : 0.75f, true);
			}
			else if (num2 < 14f && val2.HasLineOfSightToPosition(HeadPos(), 70f, 30, -1f, -1))
			{
				val2.JumpToFearLevel(0.6f, true);
			}
		}
	}

	private void UpdateStare(float dt)
	{
		//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_00cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e8: 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_00f5: 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_013c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0142: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_0168: 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_017f: 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_0190: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cb: 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_01e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d9: 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_024b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0252: Unknown result type (might be due to invalid IL or missing references)
		PlayerControllerB val = (((Object)(object)GameNetworkManager.Instance != (Object)null) ? GameNetworkManager.Instance.localPlayerController : null);
		if (!((Object)(object)val != (Object)null) || base.isEnemyDead || mjState != 3 || !(StateAge < FreezeTime) || targetId != (int)val.playerClientId || !val.isPlayerControlled || val.isPlayerDead)
		{
			ReleaseStare();
			return;
		}
		if (!staring)
		{
			staring = true;
			staringPlayer = val;
			moveWasDisabled = val.disableMoveInput;
			lookWasDisabled = val.disableLookInput;
		}
		val.disableMoveInput = true;
		val.disableLookInput = true;
		val.isSprinting = false;
		try
		{
			Camera gameplayCamera = val.gameplayCamera;
			Vector3 val2 = ((Component)this).transform.position + Vector3.up * 2.1499999f - ((Component)gameplayCamera).transform.position;
			float num = Mathf.Sqrt(val2.x * val2.x + val2.z * val2.z);
			if (!(num < 0.05f) || !(Mathf.Abs(val2.y) < 0.05f))
			{
				float num2 = 1f - Mathf.Exp(-9f * dt);
				float num3 = Mathf.Atan2(val2.x, val2.z) * 57.29578f;
				Vector3 eulerAngles = val.thisPlayerBody.eulerAngles;
				val.thisPlayerBody.eulerAngles = new Vector3(eulerAngles.x, Mathf.LerpAngle(eulerAngles.y, num3, num2), eulerAngles.z);
				float num4 = Mathf.Clamp((0f - Mathf.Atan2(val2.y, Mathf.Max(num, 0.001f))) * 57.29578f, -80f, 80f);
				Vector3 localEulerAngles = ((Component)gameplayCamera).transform.localEulerAngles;
				float num5 = ((localEulerAngles.x > 180f) ? (localEulerAngles.x - 360f) : localEulerAngles.x);
				if (CameraUpField != null)
				{
					num5 = (float)CameraUpField.GetValue(val);
				}
				float num6 = Mathf.Lerp(num5, num4, num2);
				if (CameraUpField != null)
				{
					CameraUpField.SetValue(val, num6);
				}
				((Component)gameplayCamera).transform.localEulerAngles = new Vector3(num6, localEulerAngles.y, localEulerAngles.z);
			}
		}
		catch (Exception)
		{
		}
	}

	private void ReleaseStare()
	{
		if (staring)
		{
			staring = false;
			if ((Object)(object)staringPlayer != (Object)null)
			{
				staringPlayer.disableMoveInput = moveWasDisabled;
				staringPlayer.disableLookInput = lookWasDisabled;
			}
			staringPlayer = null;
		}
	}

	private void UpdateMusic(float dt, float age)
	{
		if ((Object)(object)music == (Object)null)
		{
			return;
		}
		float num = age;
		if (mjState == 3 && !base.isEnemyDead)
		{
			AudioClip thriller = MJSounds.Thriller;
			if ((Object)(object)thriller != (Object)null && (!music.isPlaying || (Object)(object)music.clip != (Object)(object)thriller))
			{
				music.clip = thriller;
				music.loop = true;
				float num2 = Mathf.Max(0f, Plugin.MusicStartOffset.Value) + Mathf.Max(0f, age);
				music.time = ((thriller.length > 0.1f) ? (num2 % thriller.length) : 0f);
				music.Play();
			}
			musicFade = Mathf.MoveTowards(musicFade, 1f, dt * 4f);
			if (music.isPlaying && (Object)(object)music.clip != (Object)null && !MJSounds.UsingPlaceholderMusic)
			{
				float num3 = music.time - Mathf.Max(0f, Plugin.MusicStartOffset.Value);
				if (num3 >= 0f && Mathf.Abs(num3 - age) < 1.5f)
				{
					num = num3;
				}
			}
		}
		else if (musicFade > 0f)
		{
			musicFade = Mathf.MoveTowards(musicFade, 0f, dt / 1.2f);
			if (musicFade <= 0f && music.isPlaying)
			{
				music.Stop();
			}
		}
		music.volume = musicFade * Mathf.Clamp01(Plugin.MusicVolume.Value);
		if ((Object)(object)anim != (Object)null)
		{
			anim.beat = Mathf.Max(0f, num) * 118f / 60f;
			anim.danceTime = Mathf.Max(0f, Plugin.DanceStartOffset.Value) + Mathf.Max(0f, num);
		}
	}
}
public class MJAnimator : MonoBehaviour
{
	private Transform modelRoot;

	private Transform[] bones;

	private Transform hair;

	private SkinnedMeshRenderer skin;

	private MaterialPropertyBlock eyeBlock;

	private bool bound;

	private readonly Pose cur = new Pose();

	private readonly Pose target = new Pose();

	private readonly PoseSolver solver = new PoseSolver();

	private Anim mode;

	private float modeStart;

	private float phase;

	private float speed;

	private Vector3 lastPos;

	private bool first = true;

	private Quaternion hairRot;

	private bool hairInit;

	private float eyeGlow = -1f;

	[NonSerialized]
	public Vector3 leanWorld;

	[NonSerialized]
	public Transform lookTarget;

	[NonSerialized]
	public float beat;

	[NonSerialized]
	public float danceTime;

	[NonSerialized]
	public float blendRate = 13f;

	public float Speed => speed;

	public Anim Mode => mode;

	private void Awake()
	{
		Bind();
	}

	private void OnEnable()
	{
		//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)
		lastPos = ((Component)this).transform.position;
	}

	private static Transform FindDeep(Transform t, string name)
	{
		if (((Object)t).name == name)
		{
			return t;
		}
		for (int i = 0; i < t.childCount; i++)
		{
			Transform val = FindDeep(t.GetChild(i), name);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
		}
		return null;
	}

	private void Bind()
	{
		//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
		if (bound)
		{
			return;
		}
		modelRoot = ((Component)this).transform.Find("Model");
		if ((Object)(object)modelRoot == (Object)null)
		{
			return;
		}
		bones = (Transform[])(object)new Transform[17];
		for (int i = 0; i < 17; i++)
		{
			bones[i] = FindDeep(modelRoot, Rig.Names[i]);
			if ((Object)(object)bones[i] == (Object)null)
			{
				return;
			}
		}
		hair = FindDeep(modelRoot, "Hair");
		Transform val = modelRoot.Find("Body");
		skin = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<SkinnedMeshRenderer>() : null);
		bound = true;
		modeStart = Time.time;
		lastPos = ((Component)this).transform.position;
	}

	public void SetMode(Anim m)
	{
		if (m != mode)
		{
			mode = m;
			modeStart = Time.time;
		}
	}

	public void Retrigger()
	{
		modeStart = Time.time;
	}

	public void SetEyeGlow(float intensity)
	{
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: Expected O, but got Unknown
		if (!bound || (Object)(object)skin == (Object)null || Mathf.Abs(intensity - eyeGlow) < 0.004f)
		{
			return;
		}
		eyeGlow = intensity;
		try
		{
			if (eyeBlock == null)
			{
				eyeBlock = new MaterialPropertyBlock();
			}
			Color val = default(Color);
			((Color)(ref val))..ctor(intensity, intensity, intensity, 1f);
			eyeBlock.SetColor("_EmissiveColor", val);
			eyeBlock.SetColor("_EmissionColor", val);
			((Renderer)skin).SetPropertyBlock(eyeBlock, 1);
		}
		catch (Exception)
		{
		}
	}

	private void LateUpdate()
	{
		//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_0032: 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_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)
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0205: Unknown result type (might be due to invalid IL or missing references)
		//IL_020a: Unknown result type (might be due to invalid IL or missing references)
		//IL_020f: 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_0222: Unknown result type (might be due to invalid IL or missing references)
		//IL_022c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0231: Unknown result type (might be due to invalid IL or missing references)
		//IL_0247: Unknown result type (might be due to invalid IL or missing references)
		//IL_0248: Unknown result type (might be due to invalid IL or missing references)
		//IL_0252: Unknown result type (might be due to invalid IL or missing references)
		//IL_0257: Unknown result type (might be due to invalid IL or missing references)
		//IL_025c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0298: Unknown result type (might be due to invalid IL or missing references)
		//IL_029d: Unknown result type (might be due to invalid IL or missing references)
		//IL_029f: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0263: Unknown result type (might be due to invalid IL or missing references)
		//IL_0280: Unknown result type (might be due to invalid IL or missing references)
		//IL_0285: Unknown result type (might be due to invalid IL or missing references)
		//IL_028a: Unknown result type (might be due to invalid IL or missing references)
		//IL_02dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_02fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0389: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_03e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_042e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0439: Unknown result type (might be due to invalid IL or missing references)
		//IL_0440: Unknown result type (might be due to invalid IL or missing references)
		//IL_0445: Unknown result type (might be due to invalid IL or missing references)
		//IL_0460: Unknown result type (might be due to invalid IL or missing references)
		//IL_0465: Unknown result type (might be due to invalid IL or missing references)
		//IL_0479: Unknown result type (might be due to invalid IL or missing references)
		//IL_047e: Unknown result type (might be due to invalid IL or missing references)
		//IL_048a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0450: Unknown result type (might be due to invalid IL or missing references)
		//IL_0452: Unknown result type (might be due to invalid IL or missing references)
		if (!bound)
		{
			Bind();
			if (!bound)
			{
				return;
			}
		}
		float deltaTime = Time.deltaTime;
		if (deltaTime <= 0f)
		{
			return;
		}
		Vector3 position = ((Component)this).transform.position;
		Vector3 val = position - lastPos;
		val.y = 0f;
		lastPos = position;
		float num = ((Vector3)(ref val)).magnitude / deltaTime;
		if (num > 40f)
		{
			num = 0f;
		}
		speed = Mathf.Lerp(speed, num, 1f - Mathf.Exp(-9f * deltaTime));
		Anim anim = mode;
		if (mode == Anim.Walk && speed < 0.35f)
		{
			anim = Anim.Idle;
		}
		float num2 = 1.35f;
		float num3 = 0f;
		switch (anim)
		{
		case Anim.Walk:
			num3 = Mathf.Min(speed / (1.04f * num2), 2.4f);
			break;
		case Anim.Sneak:
			num3 = Mathf.Min(speed / (0.68f * num2), 2.7f);
			break;
		case Anim.Moonwalk:
			num3 = Mathf.Min(speed / (0.84f * num2), 1.9f);
			break;
		}
		phase += num3 * deltaTime;
		if (phase > 1000f)
		{
			phase -= 1000f;
		}
		float num4 = Time.time - modeStart;
		float num5 = blendRate;
		DanceClip dance = Plugin.Dance;
		if (anim == Anim.Dance && dance != null)
		{
			dance.Sample(Mathf.Max(0f, danceTime), target);
			num5 = Mathf.Lerp(9f, 45f, Mathf.Clamp01(num4 / 0.5f));
		}
		else
		{
			AnimIn a = new AnimIn
			{
				time = Time.time,
				phase = phase,
				stateTime = num4,
				beat = beat
			};
			Vector3 val2 = ((Component)this).transform.InverseTransformDirection(leanWorld);
			a.lean = new Vector3(val2.x / num2, 0f, val2.z / num2);
			if ((Object)(object)lookTarget != (Object)null)
			{
				Vector3 val3 = position + Vector3.up * 2.35f;
				if (anim == Anim.Peek)
				{
					val3 += new Vector3(leanWorld.x, 0f, leanWorld.z);
				}
				Vector3 val4 = ((Component)this).transform.InverseTransformDirection(lookTarget.position - val3);
				float num6 = Mathf.Sqrt(val4.x * val4.x + val4.z * val4.z);
				if (num6 > 0.05f)
				{
					a.lookYaw = Mathf.Atan2(val4.x, val4.z) * 57.29578f;
					a.lookPitch = (0f - Mathf.Atan2(val4.y, num6)) * 57.29578f;
				}
			}
			solver.Evaluate(anim, ref a, target);
		}
		if (first)
		{
			cur.CopyFrom(target);
			first = false;
		}
		else
		{
			cur.BlendTowards(target, 1f - Mathf.Exp((0f - num5) * deltaTime));
		}
		for (int i = 0; i < 17; i++)
		{
			bones[i].localRotation = cur.rot[i];
		}
		bones[0].localPosition = cur.hipsPos;
		modelRoot.localPosition = cur.rootPos * num2;
		modelRoot.localRotation = cur.rootRot;
		if ((Object)(object)hair != (Object)null)
		{
			float num7 = ((anim == Anim.Dead) ? Mathf.Lerp(0.8f, 0.1f, Mathf.Clamp01(num4 / 0.8f)) : 0.8f);
			Quaternion val5 = Quaternion.Slerp(bones[4].rotation, ((Component)this).transform.rotation, num7);
			if (!hairInit)
			{
				hairRot = val5;
				hairInit = true;
			}
			hairRot = Quaternion.Slerp(hairRot, val5, 1f - Mathf.Exp(-7f * deltaTime));
			hair.rotation = hairRot;
		}
	}
}
internal static class MJAssets
{
	internal sealed class Puppet
	{
		public Transform model;

		public Transform[] bones;

		public SkinnedMeshRenderer skin;
	}

	public static GameObject Prefab;

	public static EnemyType Type;

	private static GameObject holder;

	private static bool tried;

	private static Mesh bodyMesh;

	private static Material bodyMat;

	private static Material glowMat;

	private static Material sequinMat;

	private static Material headMat;

	private static Material dotMat;

	private static Texture2D paletteTex;

	private static Texture2D sequinTex;

	private static Texture2D headTex;

	public const string BodyName = "Body";

	public const string ModelName = "Model";

	public const string HairName = "Hair";

	private static Material[] showMats;

	public static bool EnsureBuilt()
	{
		if ((Object)(object)Prefab != (Object)null)
		{
			return true;
		}
		if (tried)
		{
			return false;
		}
		tried = true;
		try
		{
			Build();
			Plugin.Log.LogInfo((object)("Enemy prefab built (" + bodyMesh.vertexCount + " vertices)."));
		}
		catch (Exception ex)
		{
			Plugin.Log.LogError((object)("Failed to build the enemy prefab: " + ex));
			Prefab = null;
		}
		return (Object)(object)Prefab != (Object)null;
	}

	private static int Layer(string name, int fallback)
	{
		int num = LayerMask.NameToLayer(name);
		if (num >= 0)
		{
			return num;
		}
		return fallback;
	}

	private static void TrySetTag(GameObject go, string tag)
	{
		try
		{
			go.tag = tag;
		}
		catch (Exception)
		{
			Plugin.Log.LogWarning((object)("Tag '" + tag + "' is not defined in this game version."));
		}
	}

	private static void Build()
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Expected O, but got Unknown
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Expected O, but got Unknown
		//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f9: Expected O, but got Unknown
		//IL_013e: 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_018d: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_01be: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0343: Unknown result type (might be due to invalid IL or missing references)
		//IL_0348: Unknown result type (might be due to invalid IL or missing references)
		//IL_0359: Unknown result type (might be due to invalid IL or missing references)
		//IL_035e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0363: Unknown result type (might be due to invalid IL or missing references)
		//IL_036d: Expected O, but got Unknown
		//IL_0384: Unknown result type (might be due to invalid IL or missing references)
		//IL_0389: Unknown result type (might be due to invalid IL or missing references)
		//IL_039a: Unknown result type (might be due to invalid IL or missing references)
		//IL_039f: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ae: Expected O, but got Unknown
		//IL_0479: Unknown result type (might be due to invalid IL or missing references)
		//IL_0484: Unknown result type (might be due to invalid IL or missing references)
		//IL_048f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0559: Unknown result type (might be due to invalid IL or missing references)
		//IL_0563: Expected O, but got Unknown
		holder = new GameObject("MJStalker_PrefabHolder");
		((Object)holder).hideFlags = (HideFlags)61;
		Object.DontDestroyOnLoad((Object)(object)holder);
		holder.SetActive(false);
		int layer = Layer("Enemies", 19);
		GameObject val = new GameObject("MichaelJacksonEnemy");
		val.transform.SetParent(holder.transform, false);
		val.layer = layer;
		SetPrefabHash(val.AddComponent<NetworkObject>(), "MJStalker.MichaelJacksonEnemy");
		NavMeshAgent val2 = val.AddComponent<NavMeshAgent>();
		val2.radius = 0.45f;
		val2.height = 2.9f;
		val2.baseOffset = 0f;
		val2.speed = 4f;
		val2.angularSpeed = 320f;
		val2.acceleration = 22f;
		val2.stoppingDistance = 0f;
		val2.autoBraking = true;
		val2.obstacleAvoidanceType = (ObstacleAvoidanceType)1;
		val2.avoidancePriority = 45;
		BuildModel(val.transform, layer, out var eye);
		GameObject val3 = new GameObject("Collision");
		val3.transform.SetParent(val.transform, false);
		val3.layer = layer;
		TrySetTag(val3, "Enemy");
		CapsuleCollider obj = val3.AddComponent<CapsuleCollider>();
		((Collider)obj).isTrigger = true;
		obj.center = new Vector3(0f, 1.45f, 0f);
		obj.radius = 0.6f;
		obj.height = 2.9f;
		Rigidbody obj2 = val3.AddComponent<Rigidbody>();
		obj2.isKinematic = true;
		obj2.useGravity = false;
		GameObject val4 = new GameObject("ScanNode");
		val4.transform.SetParent(val.transform, false);
		val4.transform.localPosition = new Vector3(0f, 2.3f, 0f);
		val4.layer = Layer("ScanNode", 22);
		val4.AddComponent<BoxCollider>().size = new Vector3(0.5f, 0.5f, 0.5f);
		ScanNodeProperties obj3 = val4.AddComponent<ScanNodeProperties>();
		obj3.headerText = "Michael Jackson";
		obj3.subText = "Don't let him watch you.";
		obj3.nodeType = 1;
		obj3.minRange = 1;
		obj3.maxRange = 16;
		obj3.requiresLineOfSight = true;
		obj3.creatureScanID = -1;
		BuildMapDot(val.transform);
		AudioSource creatureVoice = MakeAudio(val.transform, "Voice", 2.5f, 3f, 30f, occlude: true);
		AudioSource creatureSFX = MakeAudio(val.transform, "SFX", 1.2f, 2f, 20f, occlude: true);
		AudioEchoFilter obj4 = ((Component)MakeAudio(val.transform, "FarVoice", 2.5f, 6f, 85f, occlude: true)).gameObject.AddComponent<AudioEchoFilter>();
		obj4.delay = 330f;
		obj4.decayRatio = 0.5f;
		obj4.dryMix = 1f;
		obj4.wetMix = 0.85f;
		AudioSource obj5 = MakeAudio(val.transform, "Music", 1.6f, 4f, 45f, occlude: true);
		obj5.loop = true;
		obj5.priority = 40;
		Type = ScriptableObject.CreateInstance<EnemyType>();
		((Object)Type).name = "MichaelJackson";
		((Object)Type).hideFlags = (HideFlags)61;
		Type.enemyName = "Michael Jackson";
		Type.enemyPrefab = val;
		Type.probabilityCurve = new AnimationCurve((Keyframe[])(object)new Keyframe[2]
		{
			new Keyframe(0f, 1f),
			new Keyframe(1f, 1f)
		});
		Type.numberSpawnedFalloff = new AnimationCurve((Keyframe[])(object)new Keyframe[2]
		{
			new Keyframe(0f, 1f),
			new Keyframe(1f, 1f)
		});
		Type.useNumberSpawnedFalloff = false;
		Type.spawningDisabled = false;
		Type.PowerLevel = Plugin.PowerLevel.Value;
		Type.DiversityPowerLevel = 0;
		Type.MaxCount = Mathf.Max(1, Plugin.MaxCount.Value);
		Type.isOutsideEnemy = false;
		Type.isDaytimeEnemy = false;
		Type.canDie = true;
		Type.canBeStunned = true;
		Type.canBeDestroyed = true;
		Type.destroyOnDeath = false;
		Type.canSeeThroughFog = true;
		Type.disableAnimatorWhenFar = false;
		Type.stunTimeMultiplier = 1f;
		Type.doorSpeedMultiplier = 1.3f;
		Type.SizeLimit = (NavSizeLimit)0;
		Type.EnemySize = (EnemySize)2;
		Type.WaterType = (EnemyWaterType)0;
		Type.timeToPlayAudio = 15f;
		Type.loudnessMultiplier = 1f;
		Type.miscAnimations = (MiscAnimation[])(object)new MiscAnimation[0];
		Type.audioClips = (AudioClip[])(object)new AudioClip[0];
		MichaelJacksonAI michaelJacksonAI = val.AddComponent<MichaelJacksonAI>();
		((EnemyAI)michaelJacksonAI).enemyType = Type;
		((EnemyAI)michaelJacksonAI).agent = val2;
		((EnemyAI)michaelJacksonAI).eye = eye;
		((EnemyAI)michaelJacksonAI).creatureVoice = creatureVoice;
		((EnemyAI)michaelJacksonAI).creatureSFX = creatureSFX;
		((EnemyAI)michaelJacksonAI).creatureAnimator = null;
		((EnemyAI)michaelJacksonAI).AIIntervalTime = 0.2f;
		((EnemyAI)michaelJacksonAI).updatePositionThreshold = 0.08f;
		((EnemyAI)michaelJacksonAI).syncMovementSpeed = 0.15f;
		((EnemyAI)michaelJacksonAI).exitVentAnimationTime = 1f;
		((EnemyAI)michaelJacksonAI).enemyHP = Mathf.Max(1, Plugin.Health.Value);
		((EnemyAI)michaelJacksonAI).currentSearch = new AISearchRoutine();
		((EnemyAI)michaelJacksonAI).enemyBehaviourStates = MichaelJacksonAI.MakeStates();
		val.AddComponent<MJAnimator>();
		val3.AddComponent<EnemyAICollisionDetect>().mainScript = (EnemyAI)(object)michaelJacksonAI;
		Prefab = val;
	}

	private static void SetPrefabHash(NetworkObject netObj, string id)
	{
		uint num;
		using (MD5 mD = MD5.Create())
		{
			num = BitConverter.ToUInt32(mD.ComputeHash(Encoding.UTF8.GetBytes(id)), 0);
		}
		FieldInfo? field = typeof(NetworkObject).GetField("GlobalObjectIdHash", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		if (field == null)
		{
			throw new MissingFieldException("NetworkObject.GlobalObjectIdHash not found");
		}
		field.SetValue(netObj, num);
	}

	private static AudioSource MakeAudio(Transform parent, string name, float height, float minDist, float maxDist, bool occlude)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Expected O, but got Unknown
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject(name);
		val.transform.SetParent(parent, false);
		val.transform.localPosition = new Vector3(0f, height, 0f);
		AudioSource obj = val.AddComponent<AudioSource>();
		obj.playOnAwake = false;
		obj.loop = false;
		obj.spatialBlend = 1f;
		obj.dopplerLevel = 0f;
		obj.rolloffMode = (AudioRolloffMode)1;
		obj.minDistance = minDist;
		obj.maxDistance = maxDist;
		obj.spread = 30f;
		if (occlude)
		{
			val.AddComponent<OccludeAudio>().useReverb = true;
		}
		return obj;
	}

	private static bool LoadHeadTexture()
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Expected O, but got Unknown
		if (Plugin.Head == null || Plugin.HeadAtlas == null)
		{
			return false;
		}
		try
		{
			Texture2D val = new Texture2D(4, 4, (TextureFormat)3, true);
			((Object)val).name = "MJ_Head";
			((Object)val).hideFlags = (HideFlags)61;
			if (!ImageConversion.LoadImage(val, Plugin.HeadAtlas, false) || ((Texture)val).width < 64)
			{
				return false;
			}
			((Texture)val).wrapMode = (TextureWrapMode)1;
			((Texture)val).filterMode = (FilterMode)2;
			((Texture)val).anisoLevel = 4;
			try
			{
				val.Compress(false);
			}
			catch (Exception)
			{
			}
			val.Apply(false, true);
			headTex = val;
			return true;
		}
		catch (Exception ex2)
		{
			Plugin.Log.LogWarning((object)("Could not decode the head texture, using the built in head: " + ex2.Message));
			return false;
		}
	}

	private static void BuildModel(Transform root, int layer, out Transform eye)
	{
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Expected O, but got Unknown
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_009b: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0203: Expected O, but got Unknown
		//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ca: Expected O, but got Unknown
		//IL_0135: Unknown result type (might be due to invalid IL or missing references)
		//IL_00da: Unknown result type (might be due to invalid IL or missing references)
		//IL_00df: 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_00ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_010b: Unknown result type (might be due to invalid IL or missing references)
		//IL_01be: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0169: 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_01b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_02fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0307: Unknown result type (might be due to invalid IL or missing references)
		//IL_030c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0311: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_03b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_03bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_03f1: Expected O, but got Unknown
		//IL_0415: Unknown result type (might be due to invalid IL or missing references)
		Rig.UseImportedHead(LoadHeadTexture() ? Plugin.Head : null);
		MeshData meshData = Rig.Build();
		GameObject val = new GameObject("Model");
		val.transform.SetParent(root, false);
		val.transform.localScale = new Vector3(1.35f, 1.35f, 1.35f);
		val.layer = layer;
		Transform[] array = MakeSkeleton(val.transform, layer);
		int count = meshData.verts.Count;
		List<Vector2> list = new List<Vector2>(count);
		BoneWeight[] array2 = (BoneWeight[])(object)new BoneWeight[count];
		float num = Rig.Palette.Length;
		for (int i = 0; i < count; i++)
		{
			if (meshData.uv[i].x >= 0f)
			{
				list.Add(meshData.uv[i]);
			}
			else if (meshData.vmat[i] == 2)
			{
				Vector3 val2 = meshData.verts[i];
				list.Add(new Vector2((val2.x + val2.z * 0.61f) * 3.2f, val2.y * 3.2f));
			}
			else
			{
				list.Add(new Vector2(((float)meshData.color[i] + 0.5f) / num, 0.5f));
			}
			BoneWeight val3;
			if (meshData.bone2[i] >= 0)
			{
				float num2 = Mathf.Clamp01(meshData.weight2[i]);
				int num3 = i;
				val3 = default(BoneWeight);
				((BoneWeight)(ref val3)).boneIndex0 = meshData.bone[i];
				((BoneWeight)(ref val3)).weight0 = 1f - num2;
				((BoneWeight)(ref val3)).boneIndex1 = meshData.bone2[i];
				((BoneWeight)(ref val3)).weight1 = num2;
				array2[num3] = val3;
			}
			else
			{
				int num4 = i;
				val3 = default(BoneWeight);
				((BoneWeight)(ref val3)).boneIndex0 = meshData.bone[i];
				((BoneWeight)(ref val3)).weight0 = 1f;
				array2[num4] = val3;
			}
		}
		bodyMesh = new Mesh();
		((Object)bodyMesh).name = "MJ_Body";
		((Object)bodyMesh).hideFlags = (HideFlags)61;
		if (count > 60000)
		{
			bodyMesh.indexFormat = (IndexFormat)1;
		}
		bodyMesh.SetVertices(meshData.verts);
		bodyMesh.SetNormals(new List<Vector3>(meshData.normals));
		bodyMesh.SetUVs(0, list);
		bodyMesh.subMeshCount = 4;
		bodyMesh.SetTriangles(meshData.tris, 0);
		bodyMesh.SetTriangles(meshData.glowTris, 1);
		bodyMesh.SetTriangles(meshData.sparkTris, 2);
		bodyMesh.SetTriangles(meshData.headTris, 3);
		bodyMesh.boneWeights = array2;
		GameObject val4 = new GameObject("Body");
		val4.transform.SetParent(val.transform, false);
		val4.layer = layer;
		Matrix4x4[] array3 = (Matrix4x4[])(object)new Matrix4x4[18];
		for (int j = 0; j < 18; j++)
		{
			array3[j] = array[j].worldToLocalMatrix * val4.transform.localToWorldMatrix;
		}
		bodyMesh.bindposes = array3;
		bodyMesh.RecalculateBounds();
		BuildMaterials();
		SkinnedMeshRenderer val5 = val4.AddComponent<SkinnedMeshRenderer>();
		val5.sharedMesh = bodyMesh;
		val5.bones = array;
		val5.rootBone = array[0];
		((Renderer)val5).sharedMaterials = (Material[])(object)new Material[4] { bodyMat, glowMat, sequinMat, headMat };
		((Renderer)val5).localBounds = new Bounds(new Vector3(0f, 0.1f, 0f), new Vector3(3f, 3.2f, 3f));
		val5.updateWhenOffscreen = false;
		((Renderer)val5).shadowCastingMode = (ShadowCastingMode)1;
		((Renderer)val5).receiveShadows = true;
		val5.quality = (SkinQuality)2;
		GameObject val6 = new GameObject("Eye");
		val6.transform.SetParent(root, false);
		val6.transform.localPosition = new Vector3(0f, 2.35f, 0.12f);
		val6.layer = layer;
		eye = val6.transform;
	}

	private static Transform[] MakeSkeleton(Transform model, int layer)
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Expected O, but got Unknown
		//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ad: Expected O, but got Unknown
		//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_0073: 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_0061: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		Transform[] array = (Transform[])(object)new Transform[18];
		for (int i = 0; i < 17; i++)
		{
			GameObject val = new GameObject(Rig.Names[i]);
			val.layer = layer;
			int num = Rig.Parent[i];
			val.transform.SetParent((num < 0) ? model : array[num], false);
			val.transform.localPosition = ((num < 0) ? Rig.Rest[i] : (Rig.Rest[i] - Rig.Rest[num]));
			val.transform.localRotation = Quaternion.identity;
			array[i] = val.transform;
		}
		GameObject val2 = new GameObject("Hair");
		val2.layer = layer;
		val2.transform.SetParent(array[4], false);
		val2.transform.localPosition = Rig.HairPivot - Rig.Rest[4];
		val2.transform.localRotation = Quaternion.identity;
		array[17] = val2.transform;
		return array;
	}

	private static Material SelfLit(Material src, float glow)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Expected O, but got Unknown
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		Material val = new Material(src);
		((Object)val).name = ((Object)src).name + "_Show";
		((Object)val).hideFlags = (HideFlags)61;
		if (val.HasProperty("_AlbedoAffectEmissive"))
		{
			SelfGlow(val, glow, Color.black);
		}
		Validate(val);
		return val;
	}

	internal static void SelfGlow(Material m, float amount, Color typical)
	{
		//IL_0059: 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_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_0076: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		SetF(m, 0f, "_EmissiveExposureWeight");
		if (m.HasProperty("_AlbedoAffectEmissive"))
		{
			m.SetFloat("_AlbedoAffectEmissive", 1f);
			SetCol(m, new Color(amount, amount, amount, 1f), "_EmissiveColor");
		}
		else
		{
			SetCol(m, new Color(typical.r * amount, typical.g * amount, typical.b * amount, 1f), "_EmissiveColor");
		}
	}

	internal static Puppet BuildPuppet(Transform parent, int layer, float glow)
	{
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Expected O, but got Unknown
		//IL_00b4: Unknown result type (might be due to invalid IL o