Decompiled source of ShadowCat v1.0.2

Packages/neoninc.ShadowCat.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using LethalLib.Modules;
using Microsoft.CodeAnalysis;
using ShadowCat.Configuration;
using Unity.Netcode;
using UnityEngine;
using neoninc.ShadowCat.NetcodePatcher;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("neoninc.ShadowCat")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("ShadowCat")]
[assembly: AssemblyTitle("neoninc.ShadowCat")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
[module: NetcodePatchedAssembly]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ExampleEnemy
{
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "neoninc.ShadowCat";

		public const string PLUGIN_NAME = "ShadowCat";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}
namespace ShadowCat
{
	[BepInPlugin("neoninc.shadowcat", "ShadowCat", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		internal static ManualLogSource Logger;

		public static AssetBundle? ModAssets;

		internal static PluginConfig BoundConfig { get; private set; }

		private void Awake()
		{
			Logger = ((BaseUnityPlugin)this).Logger;
			BoundConfig = new PluginConfig(((BaseUnityPlugin)this).Config);
			InitializeNetworkBehaviours();
			string path = "modassets";
			ModAssets = AssetBundle.LoadFromFile(Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), path));
			if ((Object)(object)ModAssets == (Object)null)
			{
				Logger.LogError((object)"Failed to load custom assets.");
				return;
			}
			EnemyType val = ModAssets.LoadAsset<EnemyType>("ShadowCat");
			TerminalNode val2 = ModAssets.LoadAsset<TerminalNode>("ShadowCatTN");
			TerminalKeyword val3 = ModAssets.LoadAsset<TerminalKeyword>("ShadowCatTK");
			NetworkPrefabs.RegisterNetworkPrefab(val.enemyPrefab);
			Enemies.RegisterEnemy(val, BoundConfig.SpawnWeight.Value, (LevelTypes)(-1), val2, val3);
			Logger.LogInfo((object)"Plugin neoninc.shadowcat is loaded!");
		}

		private static void InitializeNetworkBehaviours()
		{
			Type[] types = Assembly.GetExecutingAssembly().GetTypes();
			Type[] array = types;
			foreach (Type type in array)
			{
				MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic);
				MethodInfo[] array2 = methods;
				foreach (MethodInfo methodInfo in array2)
				{
					object[] customAttributes = methodInfo.GetCustomAttributes(typeof(RuntimeInitializeOnLoadMethodAttribute), inherit: false);
					if (customAttributes.Length != 0)
					{
						methodInfo.Invoke(null, null);
					}
				}
			}
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "neoninc.shadowcat";

		public const string PLUGIN_NAME = "ShadowCat";

		public const string PLUGIN_VERSION = "1.0.0";
	}
	internal class ShadowCatAI : EnemyAI
	{
		private enum State
		{
			Lurking,
			Stalking,
			FleeingLight,
			Hiding,
			KillAnimation
		}

		[CompilerGenerated]
		private sealed class <DissolveAndDestroy>d__38 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public ShadowCatAI <>4__this;

			private Renderer[] <renderers>5__1;

			private float <duration>5__2;

			private float <elapsed>5__3;

			private Renderer[] <>s__4;

			private int <>s__5;

			private Renderer <r>5__6;

			private Material[] <>s__7;

			private int <>s__8;

			private Material <mat>5__9;

			private float <alpha>5__10;

			private Renderer[] <>s__11;

			private int <>s__12;

			private Renderer <r>5__13;

			private Material[] <>s__14;

			private int <>s__15;

			private Material <mat>5__16;

			private Color <c>5__17;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <DissolveAndDestroy>d__38(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<renderers>5__1 = null;
				<>s__4 = null;
				<r>5__6 = null;
				<>s__7 = null;
				<mat>5__9 = null;
				<>s__11 = null;
				<r>5__13 = null;
				<>s__14 = null;
				<mat>5__16 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0034: Unknown result type (might be due to invalid IL or missing references)
				//IL_003e: Expected O, but got Unknown
				//IL_025f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0264: 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)
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = (object)new WaitForSeconds(1.5f);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					<renderers>5__1 = ((Component)<>4__this).GetComponentsInChildren<Renderer>();
					<>s__4 = <renderers>5__1;
					for (<>s__5 = 0; <>s__5 < <>s__4.Length; <>s__5++)
					{
						<r>5__6 = <>s__4[<>s__5];
						<>s__7 = <r>5__6.materials;
						for (<>s__8 = 0; <>s__8 < <>s__7.Length; <>s__8++)
						{
							<mat>5__9 = <>s__7[<>s__8];
							<mat>5__9.SetFloat("_Mode", 3f);
							<mat>5__9.SetInt("_SrcBlend", 5);
							<mat>5__9.SetInt("_DstBlend", 10);
							<mat>5__9.SetInt("_ZWrite", 0);
							<mat>5__9.DisableKeyword("_ALPHATEST_ON");
							<mat>5__9.EnableKeyword("_ALPHABLEND_ON");
							<mat>5__9.DisableKeyword("_ALPHAPREMULTIPLY_ON");
							<mat>5__9.renderQueue = 3000;
							<mat>5__9 = null;
						}
						<>s__7 = null;
						<r>5__6 = null;
					}
					<>s__4 = null;
					<duration>5__2 = 3f;
					<elapsed>5__3 = 0f;
					break;
				case 2:
					<>1__state = -1;
					break;
				}
				if (<elapsed>5__3 < <duration>5__2)
				{
					<elapsed>5__3 += Time.deltaTime;
					<alpha>5__10 = Mathf.Lerp(1f, 0f, <elapsed>5__3 / <duration>5__2);
					<>s__11 = <renderers>5__1;
					for (<>s__12 = 0; <>s__12 < <>s__11.Length; <>s__12++)
					{
						<r>5__13 = <>s__11[<>s__12];
						<>s__14 = <r>5__13.materials;
						for (<>s__15 = 0; <>s__15 < <>s__14.Length; <>s__15++)
						{
							<mat>5__16 = <>s__14[<>s__15];
							<c>5__17 = <mat>5__16.color;
							<c>5__17.a = <alpha>5__10;
							<mat>5__16.color = <c>5__17;
							<mat>5__16 = null;
						}
						<>s__14 = null;
						<r>5__13 = null;
					}
					<>s__11 = null;
					<>2__current = null;
					<>1__state = 2;
					return true;
				}
				Object.Destroy((Object)(object)((Component)<>4__this).gameObject);
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <KillPlayerAnimation>d__37 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public PlayerControllerB player;

			public ShadowCatAI <>4__this;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <KillPlayerAnimation>d__37(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0130: Unknown result type (might be due to invalid IL or missing references)
				//IL_013a: Expected O, but got Unknown
				//IL_0097: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b3: Expected O, but got Unknown
				//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
				//IL_0102: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					if (<>4__this.isKillingPlayer)
					{
						return false;
					}
					<>4__this.isKillingPlayer = true;
					((EnemyAI)<>4__this).SwitchToBehaviourClientRpc(4);
					((EnemyAI)<>4__this).agent.speed = 0f;
					((EnemyAI)<>4__this).inSpecialAnimation = true;
					((EnemyAI)<>4__this).SetDestinationToPosition(((Component)player).transform.position, false);
					<>2__current = (object)new WaitForSeconds(0.2f);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					if (((EnemyAI)<>4__this).isEnemyDead)
					{
						<>4__this.isKillingPlayer = false;
						return false;
					}
					<>4__this.DoAnimationClientRpc("killPlayer");
					<>2__current = (object)new WaitForSeconds(0.5f);
					<>1__state = 2;
					return true;
				case 2:
					<>1__state = -1;
					<>4__this.GrabAndKillClientRpc((int)player.playerClientId);
					<>2__current = (object)new WaitForSeconds(3.5f);
					<>1__state = 3;
					return true;
				case 3:
					<>1__state = -1;
					((EnemyAI)<>4__this).inSpecialAnimation = false;
					<>4__this.isKillingPlayer = false;
					<>4__this.inAngerMode = false;
					<>4__this.angerTimer = 0f;
					<>4__this.GoHide();
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		public Transform turnCompass = null;

		public Transform grabPoint = null;

		[Header("Shadow Stalker Settings")]
		public float sneakSpeed = 10f;

		public float chaseSpeed = 18f;

		public float detectionRange = 20f;

		public float senseRange = 4f;

		public float lightFearRange = 12f;

		public float retreatCooldown = 40f;

		public float killAngerTime = 4f;

		public float minFleeTime = 12f;

		private float timeSinceHittingPlayer;

		private float timeSinceSeenFlashlight;

		private float retreatTimer;

		private float angerTimer;

		private float fleeTimer;

		private bool isKillingPlayer;

		private bool isDeadAnimationDone;

		private bool inAngerMode;

		private bool hasReachedHideSpot;

		private Vector3 fleeTarget;

		private bool hasFleeTarget;

		private Random enemyRandom = null;

		private void Log(string text)
		{
			Plugin.Logger.LogInfo((object)text);
		}

		public override void Start()
		{
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			((EnemyAI)this).Start();
			Log("ShadowCat spawned.");
			timeSinceHittingPlayer = 0f;
			timeSinceSeenFlashlight = 999f;
			retreatTimer = 0f;
			angerTimer = 0f;
			fleeTimer = 0f;
			isKillingPlayer = false;
			isDeadAnimationDone = false;
			inAngerMode = false;
			hasReachedHideSpot = false;
			enemyRandom = new Random(StartOfRound.Instance.randomMapSeed + base.thisEnemyIndex);
			base.currentBehaviourStateIndex = 0;
			((EnemyAI)this).StartSearch(((Component)this).transform.position, (AISearchRoutine)null);
			base.agent.updateRotation = false;
		}

		public override void Update()
		{
			//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_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: 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_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: 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_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: 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)
			Vector3 velocity = base.agent.velocity;
			if (((Vector3)(ref velocity)).sqrMagnitude > 0.1f)
			{
				velocity = base.agent.velocity;
				Vector3 normalized = ((Vector3)(ref velocity)).normalized;
				Quaternion val = Quaternion.LookRotation(normalized);
				((Component)this).transform.rotation = Quaternion.RotateTowards(((Component)this).transform.rotation, val, 720f * Time.deltaTime);
			}
			((EnemyAI)this).Update();
			if (base.isEnemyDead)
			{
				if (isDeadAnimationDone)
				{
					return;
				}
				isDeadAnimationDone = true;
				if ((Object)(object)base.creatureVoice != (Object)null)
				{
					base.creatureVoice.Stop();
					if ((Object)(object)base.dieSFX != (Object)null)
					{
						base.creatureVoice.PlayOneShot(base.dieSFX);
					}
				}
				if ((Object)(object)base.creatureAnimator != (Object)null)
				{
					base.creatureAnimator.SetTrigger("KillEnemy");
				}
				((MonoBehaviour)this).StartCoroutine(DissolveAndDestroy());
				return;
			}
			timeSinceHittingPlayer += Time.deltaTime;
			timeSinceSeenFlashlight += Time.deltaTime;
			int currentBehaviourStateIndex = base.currentBehaviourStateIndex;
			float num = 720f;
			if ((Object)(object)base.targetPlayer != (Object)null && (currentBehaviourStateIndex == 1 || currentBehaviourStateIndex == 4))
			{
				turnCompass.LookAt(((Component)base.targetPlayer.gameplayCamera).transform.position);
				((Component)this).transform.rotation = Quaternion.RotateTowards(((Component)this).transform.rotation, Quaternion.Euler(0f, turnCompass.eulerAngles.y, 0f), num * Time.deltaTime);
			}
			if (base.stunNormalizedTimer > 0f)
			{
				base.agent.speed = 0f;
			}
			if (base.currentBehaviourStateIndex == 1 && (Object)(object)base.targetPlayer != (Object)null && PlayerFlashlightPointsAtUs(base.targetPlayer, lightFearRange))
			{
				fleeTimer = 0f;
				hasReachedHideSpot = false;
				hasFleeTarget = false;
				((EnemyAI)this).SwitchToBehaviourClientRpc(2);
			}
		}

		public override void DoAIInterval()
		{
			//IL_0114: 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_02a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02aa: 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_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0396: Unknown result type (might be due to invalid IL or missing references)
			((EnemyAI)this).DoAIInterval();
			if (base.isEnemyDead || StartOfRound.Instance.allPlayersDead || isKillingPlayer)
			{
				return;
			}
			switch (base.currentBehaviourStateIndex)
			{
			case 0:
				base.agent.speed = sneakSpeed;
				retreatTimer -= base.AIIntervalTime;
				if (!(retreatTimer > 0f) && FoundClosestPlayerInRange(detectionRange, senseRange))
				{
					Log("Found target, begin stalking.");
					((EnemyAI)this).StopSearch(base.currentSearch, true);
					angerTimer = 0f;
					((EnemyAI)this).SwitchToBehaviourClientRpc(1);
				}
				break;
			case 1:
			{
				base.agent.speed = sneakSpeed;
				angerTimer += base.AIIntervalTime;
				if (!TargetClosestPlayerInAnyCase() || (Vector3.Distance(((Component)this).transform.position, ((Component)base.targetPlayer).transform.position) > 25f && !((EnemyAI)this).CheckLineOfSightForPosition(((Component)base.targetPlayer).transform.position, 45f, 60, -1f, (Transform)null)))
				{
					Log("Lost target, going to lurk.");
					GoHide();
					break;
				}
				bool flag = PlayerHoldsActiveFlashlight(base.targetPlayer);
				if (flag)
				{
					timeSinceSeenFlashlight = 0f;
					if (PlayerFlashlightPointsAtUs(base.targetPlayer, lightFearRange))
					{
						Log("Flashlight on us — FLEEING to far end of map!");
						fleeTimer = 0f;
						hasReachedHideSpot = false;
						((EnemyAI)this).SwitchToBehaviourClientRpc(2);
						break;
					}
				}
				if (angerTimer >= killAngerTime && !inAngerMode)
				{
					Log("ANGER MODE!");
					inAngerMode = true;
					if ((Object)(object)base.creatureVoice != (Object)null && base.enemyBehaviourStates.Length > 1)
					{
						base.creatureVoice.PlayOneShot(base.enemyBehaviourStates[1].VoiceClip);
					}
				}
				StalkBehavior(base.targetPlayer, flag);
				break;
			}
			case 2:
				base.agent.speed = chaseSpeed;
				fleeTimer += base.AIIntervalTime;
				if (!hasFleeTarget)
				{
					fleeTarget = GetFleePointFromPlayer(base.targetPlayer);
					hasFleeTarget = true;
					((EnemyAI)this).SetDestinationToPosition(fleeTarget, true);
				}
				if (!base.agent.pathPending && base.agent.remainingDistance < 2f)
				{
					hasReachedHideSpot = true;
					hasFleeTarget = false;
					((EnemyAI)this).SwitchToBehaviourClientRpc(3);
				}
				break;
			case 3:
				base.agent.speed = 0f;
				fleeTimer += base.AIIntervalTime;
				if (!(fleeTimer < minFleeTime) && !AnyPlayerWithActiveLightNearby(25f))
				{
					Log("No light nearby, resuming hunt.");
					inAngerMode = false;
					angerTimer = 0f;
					fleeTimer = 0f;
					retreatTimer = 2f;
					((EnemyAI)this).StartSearch(((Component)this).transform.position, (AISearchRoutine)null);
					((EnemyAI)this).SwitchToBehaviourClientRpc(0);
				}
				break;
			case 4:
				break;
			default:
				Log("Unknown state!");
				break;
			}
		}

		private Vector3 GetFarthestPoint()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: 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_008f: 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_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: 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_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: 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)
			Vector3 val = Vector3.zero;
			int num = 0;
			for (int i = 0; i < StartOfRound.Instance.connectedPlayersAmount + 1; i++)
			{
				PlayerControllerB val2 = StartOfRound.Instance.allPlayerScripts[i];
				if ((Object)(object)val2 != (Object)null && !val2.isPlayerDead)
				{
					val += ((Component)val2).transform.position;
					num++;
				}
			}
			if (num == 0)
			{
				return ((Component)this).transform.position;
			}
			val /= (float)num;
			Transform val3 = ((EnemyAI)this).ChooseFarthestNodeFromPosition(val, false, 0, false, 50, false);
			return ((Object)(object)val3 != (Object)null) ? val3.position : ((Component)this).transform.position;
		}

		private Vector3 GetFleePointFromPlayer(PlayerControllerB player)
		{
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: 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_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_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: 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_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: 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_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player == (Object)null)
			{
				return ((Component)this).transform.position;
			}
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor((float)(enemyRandom.NextDouble() - 0.5) * 6f, 0f, (float)(enemyRandom.NextDouble() - 0.5) * 6f);
			Vector3 val2 = ((Component)this).transform.position - ((Component)player).transform.position;
			Vector3 normalized = ((Vector3)(ref val2)).normalized;
			Vector3 val3 = ((Component)this).transform.position + val + normalized * 20f;
			Transform val4 = ((EnemyAI)this).ChooseClosestNodeToPosition(val3, false, 0);
			if ((Object)(object)val4 != (Object)null)
			{
				return val4.position;
			}
			return val3;
		}

		private void RunToFarthestPointFromAllPlayers()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: 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_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			if (!((NetworkBehaviour)this).IsOwner)
			{
				return;
			}
			Vector3 val = Vector3.zero;
			int num = 0;
			for (int i = 0; i < StartOfRound.Instance.connectedPlayersAmount + 1; i++)
			{
				PlayerControllerB val2 = StartOfRound.Instance.allPlayerScripts[i];
				if ((Object)(object)val2 != (Object)null && !val2.isPlayerDead)
				{
					val += ((Component)val2).transform.position;
					num++;
				}
			}
			if (num != 0)
			{
				val /= (float)num;
				Transform val3 = ((EnemyAI)this).ChooseFarthestNodeFromPosition(val, false, 0, false, 50, false);
				if ((Object)(object)val3 != (Object)null)
				{
					((EnemyAI)this).SetDestinationToPosition(val3.position, false);
				}
			}
		}

		private bool AnyPlayerWithActiveLightNearby(float range)
		{
			//IL_0031: 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)
			for (int i = 0; i < StartOfRound.Instance.connectedPlayersAmount + 1; i++)
			{
				PlayerControllerB val = StartOfRound.Instance.allPlayerScripts[i];
				if (!((Object)(object)val == (Object)null) && !val.isPlayerDead && !(Vector3.Distance(((Component)this).transform.position, ((Component)val).transform.position) > range) && PlayerHoldsActiveFlashlight(val))
				{
					return true;
				}
			}
			return false;
		}

		private bool PlayerHoldsActiveFlashlight(PlayerControllerB player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return false;
			}
			GrabbableObject currentlyHeldObjectServer = player.currentlyHeldObjectServer;
			if ((Object)(object)currentlyHeldObjectServer == (Object)null)
			{
				return false;
			}
			FlashlightItem val = (FlashlightItem)(object)((currentlyHeldObjectServer is FlashlightItem) ? currentlyHeldObjectServer : null);
			if (val != null)
			{
				int result;
				if (((GrabbableObject)val).isBeingUsed)
				{
					Battery insertedBattery = currentlyHeldObjectServer.insertedBattery;
					result = ((insertedBattery != null && insertedBattery.charge > 0f) ? 1 : 0);
				}
				else
				{
					result = 0;
				}
				return (byte)result != 0;
			}
			return false;
		}

		private bool PlayerFlashlightPointsAtUs(PlayerControllerB player, float range)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			if (!PlayerHoldsActiveFlashlight(player))
			{
				return false;
			}
			if (Vector3.Distance(((Component)this).transform.position, ((Component)player).transform.position) > range)
			{
				return false;
			}
			Vector3 val = ((Component)this).transform.position - ((Component)player.gameplayCamera).transform.position;
			Vector3 normalized = ((Vector3)(ref val)).normalized;
			Vector3 forward = ((Component)player.gameplayCamera).transform.forward;
			return Vector3.Angle(forward, normalized) < 50f;
		}

		private void StalkBehavior(PlayerControllerB target, bool targetHasFlashlight)
		{
			//IL_0022: 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_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			if (!((NetworkBehaviour)this).IsOwner || (Object)(object)target == (Object)null)
			{
				return;
			}
			float num = Vector3.Distance(((Component)this).transform.position, ((Component)target).transform.position);
			if (targetHasFlashlight && !inAngerMode)
			{
				Vector3 val = ((Component)target).transform.position - ((Component)target).transform.forward * 8f + new Vector3((float)(enemyRandom.NextDouble() - 0.5) * 3f, 0f, (float)(enemyRandom.NextDouble() - 0.5) * 3f);
				((EnemyAI)this).SetDestinationToPosition(val, false);
				return;
			}
			((EnemyAI)this).SetDestinationToPosition(((Component)target).transform.position, false);
			if (num < 2.5f && timeSinceHittingPlayer > 1.5f)
			{
				Log("Close enough! Starting kill.");
				((MonoBehaviour)this).StartCoroutine(KillPlayerAnimation(target));
			}
		}

		private void GoHide()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			retreatTimer = retreatCooldown;
			inAngerMode = false;
			((EnemyAI)this).StartSearch(((Component)this).transform.position, (AISearchRoutine)null);
			((EnemyAI)this).SwitchToBehaviourClientRpc(0);
		}

		private bool FoundClosestPlayerInRange(float range, float senseRange)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			((EnemyAI)this).TargetClosestPlayer(1.5f, true, 70f);
			if ((Object)(object)base.targetPlayer == (Object)null)
			{
				((EnemyAI)this).TargetClosestPlayer(1.5f, false, 70f);
				range = senseRange;
			}
			return (Object)(object)base.targetPlayer != (Object)null && Vector3.Distance(((Component)this).transform.position, ((Component)base.targetPlayer).transform.position) < range;
		}

		private bool TargetClosestPlayerInAnyCase()
		{
			//IL_001e: 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)
			base.mostOptimalDistance = 2000f;
			base.targetPlayer = null;
			for (int i = 0; i < StartOfRound.Instance.connectedPlayersAmount + 1; i++)
			{
				float num = Vector3.Distance(((Component)this).transform.position, ((Component)StartOfRound.Instance.allPlayerScripts[i]).transform.position);
				if (num < base.mostOptimalDistance)
				{
					base.mostOptimalDistance = num;
					base.targetPlayer = StartOfRound.Instance.allPlayerScripts[i];
				}
			}
			return (Object)(object)base.targetPlayer != (Object)null;
		}

		[IteratorStateMachine(typeof(<KillPlayerAnimation>d__37))]
		private IEnumerator KillPlayerAnimation(PlayerControllerB player)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <KillPlayerAnimation>d__37(0)
			{
				<>4__this = this,
				player = player
			};
		}

		[IteratorStateMachine(typeof(<DissolveAndDestroy>d__38))]
		private IEnumerator DissolveAndDestroy()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <DissolveAndDestroy>d__38(0)
			{
				<>4__this = this
			};
		}

		public override void OnCollideWithPlayer(Collider other)
		{
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			if (!(timeSinceHittingPlayer < 1f) && !isKillingPlayer)
			{
				PlayerControllerB val = ((EnemyAI)this).MeetsStandardPlayerCollisionConditions(other, false, false);
				if ((Object)(object)val != (Object)null && (inAngerMode || !PlayerHoldsActiveFlashlight(val)))
				{
					Log("Collision damage!");
					timeSinceHittingPlayer = 0f;
					val.DamagePlayer(30, true, true, (CauseOfDeath)0, 0, false, default(Vector3));
				}
				if (base.currentBehaviourStateIndex != 2)
				{
				}
			}
		}

		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)
			{
				if ((Object)(object)base.creatureVoice != (Object)null && base.enemyBehaviourStates.Length != 0 && (Object)(object)base.enemyBehaviourStates[0].VoiceClip != (Object)null)
				{
					base.creatureVoice.PlayOneShot(base.enemyBehaviourStates[0].VoiceClip);
				}
				base.enemyHP -= force;
				if (!inAngerMode)
				{
					Log("Hit! Anger mode.");
					inAngerMode = true;
					angerTimer = killAngerTime;
				}
				if (((NetworkBehaviour)this).IsOwner && base.enemyHP <= 0 && !base.isEnemyDead)
				{
					((MonoBehaviour)this).StopCoroutine(base.searchCoroutine);
					((EnemyAI)this).KillEnemyOnOwnerClient(false);
				}
			}
		}

		[ClientRpc]
		public void DoAnimationClientRpc(string animationName)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Invalid comparison between Unknown and I4
			//IL_005f: 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_006d: 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_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)((NetworkBehaviour)this).__rpc_exec_stage != 1 && (networkManager.IsServer || networkManager.IsHost))
			{
				ClientRpcParams val = default(ClientRpcParams);
				FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(387855304u, val, (RpcDelivery)0);
				bool flag = animationName != null;
				((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag, default(ForPrimitives));
				if (flag)
				{
					((FastBufferWriter)(ref val2)).WriteValueSafe(animationName, false);
				}
				((NetworkBehaviour)this).__endSendClientRpc(ref val2, 387855304u, val, (RpcDelivery)0);
			}
			if ((int)((NetworkBehaviour)this).__rpc_exec_stage == 1 && (networkManager.IsClient || networkManager.IsHost))
			{
				((NetworkBehaviour)this).__rpc_exec_stage = (__RpcExecStage)0;
				Log("Animation: " + animationName);
				base.creatureAnimator.SetTrigger(animationName);
			}
		}

		[ClientRpc]
		public void GrabAndKillClientRpc(int playerObjectId)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Invalid comparison between Unknown and I4
			//IL_005f: 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_006d: 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_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)((NetworkBehaviour)this).__rpc_exec_stage != 1 && (networkManager.IsServer || networkManager.IsHost))
			{
				ClientRpcParams val = default(ClientRpcParams);
				FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(626745955u, val, (RpcDelivery)0);
				BytePacker.WriteValueBitPacked(val2, playerObjectId);
				((NetworkBehaviour)this).__endSendClientRpc(ref val2, 626745955u, val, (RpcDelivery)0);
			}
			if ((int)((NetworkBehaviour)this).__rpc_exec_stage == 1 && (networkManager.IsClient || networkManager.IsHost))
			{
				((NetworkBehaviour)this).__rpc_exec_stage = (__RpcExecStage)0;
				Log($"GrabAndKill on player {playerObjectId}");
				PlayerControllerB val3 = StartOfRound.Instance.allPlayerScripts[playerObjectId];
				if (!((Object)(object)val3 == (Object)null) && !val3.isPlayerDead)
				{
					timeSinceHittingPlayer = 0f;
					val3.inAnimationWithEnemy = (EnemyAI)(object)this;
					val3.KillPlayer(Vector3.zero, true, (CauseOfDeath)4, 1, default(Vector3));
				}
			}
		}

		protected override void __initializeVariables()
		{
			((EnemyAI)this).__initializeVariables();
		}

		protected override void __initializeRpcs()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			((NetworkBehaviour)this).__registerRpc(387855304u, new RpcReceiveHandler(__rpc_handler_387855304), "DoAnimationClientRpc");
			((NetworkBehaviour)this).__registerRpc(626745955u, new RpcReceiveHandler(__rpc_handler_626745955), "GrabAndKillClientRpc");
			((EnemyAI)this).__initializeRpcs();
		}

		private static void __rpc_handler_387855304(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//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_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				bool flag = default(bool);
				((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref flag, default(ForPrimitives));
				string animationName = null;
				if (flag)
				{
					((FastBufferReader)(ref reader)).ReadValueSafe(ref animationName, false);
				}
				target.__rpc_exec_stage = (__RpcExecStage)1;
				((ShadowCatAI)(object)target).DoAnimationClientRpc(animationName);
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		private static void __rpc_handler_626745955(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//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_0050: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				int playerObjectId = default(int);
				ByteUnpacker.ReadValueBitPacked(reader, ref playerObjectId);
				target.__rpc_exec_stage = (__RpcExecStage)1;
				((ShadowCatAI)(object)target).GrabAndKillClientRpc(playerObjectId);
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		protected internal override string __getTypeName()
		{
			return "ShadowCatAI";
		}
	}
}
namespace ShadowCat.Configuration
{
	public class PluginConfig
	{
		public ConfigEntry<int> SpawnWeight;

		public PluginConfig(ConfigFile cfg)
		{
			SpawnWeight = cfg.Bind<int>("General", "Spawn weight", 70, "The spawn chance weight for ShadowCat, relative to other existing enemies.\nGoes up from 0, lower is more rare, 100 and up is very common.");
			ClearUnusedEntries(cfg);
		}

		private void ClearUnusedEntries(ConfigFile cfg)
		{
			PropertyInfo property = ((object)cfg).GetType().GetProperty("OrphanedEntries", BindingFlags.Instance | BindingFlags.NonPublic);
			Dictionary<ConfigDefinition, string> dictionary = (Dictionary<ConfigDefinition, string>)property.GetValue(cfg, null);
			dictionary.Clear();
			cfg.Save();
		}
	}
}
namespace __GEN
{
	internal class NetworkVariableSerializationHelper
	{
		[RuntimeInitializeOnLoadMethod]
		internal static void InitializeSerialization()
		{
		}
	}
}
namespace neoninc.ShadowCat.NetcodePatcher
{
	[AttributeUsage(AttributeTargets.Module)]
	internal class NetcodePatchedAssemblyAttribute : Attribute
	{
	}
}