Decompiled source of MindControl v0.0.6

MindControl.dll

Decompiled 2 months ago
using System;
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 AIGraph;
using API;
using Agents;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using BepInEx.Unity.IL2CPP.Hook;
using Enemies;
using HarmonyLib;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.Injection;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppInterop.Runtime.Runtime;
using Il2CppInterop.Runtime.Runtime.VersionSpecific.Class;
using Il2CppInterop.Runtime.Runtime.VersionSpecific.MethodInfo;
using Il2CppSystem.Collections.Generic;
using Il2CppSystem.Runtime.InteropServices;
using LevelGeneration;
using Microsoft.CodeAnalysis;
using MindControl.API;
using MindControl.BepInEx;
using Player;
using ReplayRecorder;
using ReplayRecorder.API.Attributes;
using ReplayRecorder.Net;
using SNetwork;
using StateMachines;
using UnityEngine;
using UnityEngine.AI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("MindControl")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+8baf03d82fdb545d3f993fb4ecd001a7d22a9c7d")]
[assembly: AssemblyProduct("MindControl")]
[assembly: AssemblyTitle("MindControl")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace API
{
	internal static class APILogger
	{
		private static readonly ManualLogSource logger;

		static APILogger()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Expected O, but got Unknown
			logger = new ManualLogSource("Rand-API");
			Logger.Sources.Add((ILogSource)(object)logger);
		}

		private static string Format(string module, object msg)
		{
			return $"[{module}]: {msg}";
		}

		public static void Info(string module, object data)
		{
			logger.LogMessage((object)Format(module, data));
		}

		public static void Verbose(string module, object data)
		{
		}

		public static void Log(object data)
		{
			logger.LogDebug((object)Format("MindControl", data));
		}

		public static void Debug(object data)
		{
			if (ConfigManager.Debug)
			{
				Log(data);
			}
		}

		public static void Warn(object data)
		{
			logger.LogWarning((object)Format("MindControl", data));
		}

		public static void Error(object data)
		{
			logger.LogError((object)Format("MindControl", data));
		}
	}
}
namespace MindControl
{
	[HarmonyPatch]
	public class EnemyController : MonoBehaviour
	{
		[HarmonyPatch]
		internal static class Patches
		{
			public static bool DontRecurse = false;

			private static bool patch = true;

			[HarmonyPatch(typeof(EnemySync), "OnSpawn")]
			[HarmonyPostfix]
			private static void Postfix_OnSpawn(EnemySync __instance, pEnemySpawnData spawnData)
			{
				if (SNet.IsMaster)
				{
					EnemyAgent agent = __instance.m_agent;
					if (!((Object)(object)((Component)agent).GetComponent<PouncerBehaviour>() != (Object)null) && !agent.EnemyBehaviorData.IsFlyer)
					{
						((Component)agent).gameObject.AddComponent<EnemyController>().AssignAgent(agent);
					}
				}
			}

			[HarmonyPatch(typeof(EnemyBehaviour), "UpdateState")]
			[HarmonyPrefix]
			private static void Prefix_UpdateState(EnemyBehaviour __instance)
			{
				if (!DontRecurse && !(__instance.m_updatebehaviour >= Clock.Time) && controllers.TryGetValue(((Agent)__instance.m_ai.m_enemyAgent).GlobalID, out EnemyController value))
				{
					value.UpdateBehaviour();
				}
			}

			[HarmonyPatch(typeof(EB_InCombat_MoveToPoint), "UpdateBehaviour")]
			[HarmonyPrefix]
			private static bool Prefix_UpdateBehaviour(EB_InCombat_MoveToPoint __instance)
			{
				if (!SNet.IsMaster)
				{
					return true;
				}
				EnemyAI ai = ((EB_StateBase)__instance).m_ai;
				if (!controllers.TryGetValue(((Agent)ai.m_enemyAgent).GlobalID, out EnemyController value) || !value.IsControlled)
				{
					return true;
				}
				if (value.commandBuffer.Peek().type == Command.Type.Attack)
				{
					return true;
				}
				return false;
			}

			[HarmonyPatch(typeof(EnemyCourseNavigation), "UpdateTracking")]
			[HarmonyPostfix]
			[HarmonyPriority(0)]
			private static void UpdateTracking(EnemyCourseNavigation __instance)
			{
				if (!patch || !SNet.IsMaster)
				{
					return;
				}
				EnemyAI aI = __instance.m_owner.AI;
				if (controllers.TryGetValue(((Agent)aI.m_enemyAgent).GlobalID, out EnemyController value) && value.IsControlled)
				{
					Command command = value.commandBuffer.Peek();
					if (command.type == Command.Type.Attack && (Object)(object)command.target != (Object)null)
					{
						patch = false;
						((AgentAI)aI).SetTarget((Agent)(object)command.target);
						patch = true;
					}
					else if (command.type == Command.Type.MoveAttack && (Object)(object)value.currentTarget != (Object)null)
					{
						patch = false;
						((AgentAI)aI).SetTarget((Agent)(object)value.currentTarget);
						patch = true;
					}
				}
			}

			[HarmonyPatch(typeof(EB_InCombat), "TryAttacks")]
			[HarmonyPrefix]
			private static bool Prefix_TryAttacks(EB_InCombat __instance, ref bool __result)
			{
				if (!SNet.IsMaster)
				{
					return true;
				}
				EnemyAI ai = ((EB_StateBase)__instance).m_ai;
				if (!controllers.TryGetValue(((Agent)ai.m_enemyAgent).GlobalID, out EnemyController value) || !value.IsControlled)
				{
					return true;
				}
				Command.Type type = value.commandBuffer.Peek().type;
				if ((uint)(type - 1) <= 1u)
				{
					return true;
				}
				__result = false;
				return false;
			}

			[HarmonyPatch(typeof(EB_InCombat), "TryStrafe")]
			[HarmonyPrefix]
			private static bool Prefix_TryStrafe(EB_InCombat __instance, ref bool __result)
			{
				if (!SNet.IsMaster)
				{
					return true;
				}
				EnemyAI ai = ((EB_StateBase)__instance).m_ai;
				if (!controllers.TryGetValue(((Agent)ai.m_enemyAgent).GlobalID, out EnemyController value) || !value.IsControlled)
				{
					return true;
				}
				if (value.commandBuffer.Peek().type == Command.Type.Attack)
				{
					if ((((AgentAI)ai).Abilities.HasAbility((AgentAbility)1) && !((AgentAI)ai).Abilities.IsAbilityReady((AgentAbility)1, 0)) || (((AgentAI)ai).Abilities.HasAbility((AgentAbility)2) && !((AgentAI)ai).Abilities.IsAbilityReady((AgentAbility)2, 0)))
					{
						return true;
					}
					__result = false;
					return false;
				}
				__result = false;
				return false;
			}

			[HarmonyPatch(typeof(EB_InCombat), "TryScream")]
			[HarmonyPrefix]
			private static bool Prefix_TryScream(EB_InCombat __instance, ref bool __result)
			{
				if (!SNet.IsMaster)
				{
					return true;
				}
				EnemyAI ai = ((EB_StateBase)__instance).m_ai;
				if (!controllers.TryGetValue(((Agent)ai.m_enemyAgent).GlobalID, out EnemyController value) || !value.IsControlled)
				{
					return true;
				}
				__result = false;
				return false;
			}

			[HarmonyPatch(typeof(EB_InCombat), "TryUpdateNavigation")]
			[HarmonyPrefix]
			private static bool Prefix_TryUpdateNavigation(EB_InCombat __instance, out bool __result, EnemyCourseNavigationMode currentExpectedMode)
			{
				__result = false;
				if (!controllers.TryGetValue(((Agent)((EB_StateBase)__instance).m_ai.m_enemyAgent).GlobalID, out EnemyController value) || !value.IsControlled)
				{
					return true;
				}
				return false;
			}

			[HarmonyPatch(typeof(EB_InCombat_MoveToPoint), "UpdateBehaviourStuckingCheck")]
			[HarmonyPrefix]
			private static bool Prefix_UpdateBehaviourStuckingCheck(EB_InCombat_MoveToPoint __instance)
			{
				if (!controllers.TryGetValue(((Agent)((EB_StateBase)__instance).m_ai.m_enemyAgent).GlobalID, out EnemyController value) || !value.IsControlled)
				{
					return true;
				}
				return false;
			}
		}

		public class Command
		{
			public enum Type
			{
				Move,
				Attack,
				MoveAttack
			}

			public Type type;

			public PlayerAgent? target;

			public Vector3 position;

			public Command(Vector3 pos)
			{
				//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)
				type = Type.Move;
				position = pos;
			}

			public Command(PlayerAgent target)
			{
				type = Type.Attack;
				this.target = target;
			}
		}

		private class NavData
		{
			public Dictionary<int, int> nodeDistanceMap = new Dictionary<int, int>();
		}

		public static Dictionary<int, EnemyController> controllers = new Dictionary<int, EnemyController>();

		private int globalId;

		private EnemyAgent agent;

		private EnemyAI ai;

		private EnemyLocomotion locomotion;

		private EnemyBehaviour behaviour;

		private EnemyBehaviourData behaviourData;

		private EB_InCombat EBInCombat;

		public Queue<Command> commandBuffer = new Queue<Command>();

		private PlayerAgent? currentTarget;

		private Vector3 destination;

		private AIG_CourseNode? destinationCourseNode;

		private AIG_CoursePortal? targetPortal;

		private Vector3 towardsPortalPosition;

		private Vector3 throughPortalPosition;

		private static Dictionary<int, NavData> navDataMap = new Dictionary<int, NavData>();

		public bool IsControlled
		{
			get
			{
				if (agent.m_alive)
				{
					return commandBuffer.Count > 0;
				}
				return false;
			}
		}

		public void AssignAgent(EnemyAgent agent)
		{
			this.agent = agent;
			globalId = ((Agent)this.agent).GlobalID;
			locomotion = agent.Locomotion;
			ai = agent.AI;
			behaviour = ai.m_behaviour;
			EBInCombat = ((Il2CppObjectBase)((StateMachine<EB_StateBase>)(object)behaviour).m_states[5]).Cast<EB_InCombat>();
			behaviourData = ai.m_behaviourData;
			controllers.Add(globalId, this);
		}

		private void OnDestroy()
		{
			controllers.Remove(globalId);
		}

		public void AddPosition(Vector3 pos)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			commandBuffer.Enqueue(new Command(pos));
		}

		public void AddAttackPosition(Vector3 pos)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			Command command = new Command(pos);
			command.type = Command.Type.MoveAttack;
			commandBuffer.Enqueue(command);
		}

		public void AddTarget(PlayerAgent target)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			if (target.m_alive)
			{
				commandBuffer.Enqueue(new Command(target));
			}
			else
			{
				commandBuffer.Enqueue(new Command(((Agent)target).m_position));
			}
		}

		public void ClearCommands()
		{
			if (commandBuffer.Count > 0)
			{
				commandBuffer.Clear();
				behaviourData.m_advanceTimer = 0f;
				Patches.DontRecurse = true;
				behaviour.ChangeState((EB_States)5);
				behaviour.m_updatebehaviour = 0f;
				((StateMachine<EB_StateBase>)(object)behaviour).UpdateState();
				Patches.DontRecurse = false;
			}
		}

		public void Suicide()
		{
			//IL_001d: 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_0028: Unknown result type (might be due to invalid IL or missing references)
			PlayerAgent localPlayerAgent = PlayerManager.GetLocalPlayerAgent();
			agent.Damage.BulletDamage(100000f, (Agent)null, ((Component)localPlayerAgent).transform.position, ((Agent)localPlayerAgent).TargetLookDir, Vector3.up, true, 0, 100f, 100f, 0u);
		}

		public void UpdateBehaviour()
		{
			if (IsControlled)
			{
				Command command = commandBuffer.Peek();
				switch (command.type)
				{
				case Command.Type.Move:
				case Command.Type.MoveAttack:
					MoveCommand(command);
					break;
				case Command.Type.Attack:
					AttackCommand(command);
					break;
				}
			}
		}

		private void AttackCommand(Command command)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Invalid comparison between Unknown and I4
			if ((int)((AgentAI)ai).Mode != 1)
			{
				((AgentAI)ai).Mode = (AgentMode)1;
				((AgentAI)ai).ModeChange();
			}
			if (((Il2CppObjectBase)((StateMachine<EB_StateBase>)(object)behaviour).m_currentState).TryCast<EB_Hibernating>() != null)
			{
				locomotion.ChangeState((ES_StateEnum)2);
				Patches.DontRecurse = true;
				behaviour.ChangeState((EB_States)5);
				Patches.DontRecurse = false;
			}
			behaviourData.m_advanceTimer = 0f;
			if (!((Object)(object)command.target == (Object)null))
			{
				if (((AgentAI)ai).m_target == null || (Object)(object)((AgentAI)ai).m_target.m_agent == (Object)null || ((AgentAI)ai).m_target.m_agent.GlobalID != ((Agent)command.target).GlobalID)
				{
					((AgentAI)ai).SetTarget((Agent)(object)command.target);
				}
				if (!((Agent)command.target).Alive)
				{
					commandBuffer.Dequeue();
					APILogger.Debug("Target dead!");
				}
			}
		}

		private void MoveCommand(Command command)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Invalid comparison between Unknown and I4
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Invalid comparison between Unknown and I4
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Invalid comparison between Unknown and I4
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Invalid comparison between Unknown and I4
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Invalid comparison between Unknown and I4
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Invalid comparison between Unknown and I4
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: 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_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Invalid comparison between Unknown and I4
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0224: Unknown result type (might be due to invalid IL or missing references)
			//IL_0226: Invalid comparison between Unknown and I4
			//IL_021a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Invalid comparison between Unknown and I4
			//IL_029b: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c5: 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_02b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0512: Unknown result type (might be due to invalid IL or missing references)
			//IL_0312: Unknown result type (might be due to invalid IL or missing references)
			//IL_0322: Unknown result type (might be due to invalid IL or missing references)
			//IL_0386: Unknown result type (might be due to invalid IL or missing references)
			//IL_038c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0391: 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)
			//IL_0401: Unknown result type (might be due to invalid IL or missing references)
			//IL_0406: Unknown result type (might be due to invalid IL or missing references)
			//IL_0417: Unknown result type (might be due to invalid IL or missing references)
			//IL_041c: Unknown result type (might be due to invalid IL or missing references)
			//IL_043f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0446: Invalid comparison between Unknown and I4
			//IL_044d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0454: Invalid comparison between Unknown and I4
			//IL_04f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_045b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0462: Invalid comparison between Unknown and I4
			//IL_0470: 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_0495: Unknown result type (might be due to invalid IL or missing references)
			//IL_049a: Unknown result type (might be due to invalid IL or missing references)
			//IL_049f: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d2: Unknown result type (might be due to invalid IL or missing references)
			ES_StateEnum val = (ES_StateEnum)((MachineState<ES_Base>)(object)((StateMachine<ES_Base>)(object)locomotion).m_currentState).ENUM_ID;
			Vector3 val2;
			if (command.type == Command.Type.MoveAttack)
			{
				if ((Object)(object)currentTarget != (Object)null)
				{
					float max = agent.EnemyBehaviorData.MeleeAttackDistance.Max;
					float max2 = agent.EnemyBehaviorData.RangedAttackDistance.Max;
					val2 = ((Agent)currentTarget).m_position - ((Agent)agent).m_position;
					float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude;
					if (((AgentAI)ai).Abilities.HasAbility((AgentAbility)1) && sqrMagnitude >= max && ((AgentAI)ai).Abilities.HasAbility((AgentAbility)2) && sqrMagnitude >= max2)
					{
						currentTarget = null;
					}
				}
				if ((Object)(object)currentTarget == (Object)null)
				{
					float num = float.MaxValue;
					Enumerator<PlayerAgent> enumerator = PlayerManager.PlayerAgentsInLevel.GetEnumerator();
					while (enumerator.MoveNext())
					{
						PlayerAgent current = enumerator.Current;
						if (current.m_alive)
						{
							val2 = ((Agent)current).m_position - ((Agent)agent).m_position;
							float sqrMagnitude2 = ((Vector3)(ref val2)).sqrMagnitude;
							if (sqrMagnitude2 < num)
							{
								num = sqrMagnitude2;
								currentTarget = current;
							}
						}
					}
				}
				if ((Object)(object)currentTarget != (Object)null && currentTarget.m_alive)
				{
					((AgentAI)ai).SetTarget((Agent)(object)currentTarget);
					if (EBInCombat.TryAttacks() || val - 18 <= 1 || (int)val == 23)
					{
						return;
					}
				}
			}
			if ((int)val <= 10)
			{
				if ((int)val == 7 || (int)val == 10)
				{
					return;
				}
			}
			else if (val - 24 <= 1 || (int)val == 29)
			{
				return;
			}
			if ((int)((AgentAI)ai).Mode != 1)
			{
				((AgentAI)ai).Mode = (AgentMode)1;
				((AgentAI)ai).ModeChange();
			}
			if (((AgentAI)ai).m_target == null || !((AgentAI)ai).m_target.m_hasLineOfSight)
			{
				EnemyAgent enemyAgent = ai.m_enemyAgent;
				val2 = destination - ((Component)ai).transform.position;
				((Agent)enemyAgent).TargetLookDir = ((Vector3)(ref val2)).normalized;
			}
			else
			{
				((Agent)ai.m_enemyAgent).TargetLookDir = ((AgentAI)ai).m_target.m_dir;
			}
			if ((int)val != 2)
			{
				locomotion.ChangeState((ES_StateEnum)2);
			}
			if (((MachineState<EB_StateBase>)(object)((StateMachine<EB_StateBase>)(object)behaviour).m_currentState).ENUM_ID != 6)
			{
				Patches.DontRecurse = true;
				behaviour.ChangeState((EB_States)6);
				behaviour.m_updatebehaviour = 0f;
				((StateMachine<EB_StateBase>)(object)behaviour).UpdateState();
				Patches.DontRecurse = false;
			}
			EBInCombat.UpdateAvoidance();
			if (!((AgentAI)ai).m_navMeshAgent.isOnNavMesh)
			{
				return;
			}
			NavMeshHit val3 = default(NavMeshHit);
			if (NavMesh.SamplePosition(command.position, ref val3, 1f, 1))
			{
				destination = ((NavMeshHit)(ref val3)).position;
			}
			else
			{
				destination = command.position;
			}
			destinationCourseNode = GetNode(destination);
			if (destinationCourseNode != null)
			{
				AIG_CourseNode courseNode = ((Agent)agent).CourseNode;
				if (courseNode.NodeID != destinationCourseNode.NodeID && courseNode.m_dimension.DimensionIndex == destinationCourseNode.m_dimension.DimensionIndex)
				{
					NavData navData = GetNavData(destinationCourseNode);
					int num2 = int.MaxValue;
					float num3 = float.MaxValue;
					AIG_CoursePortal val4 = null;
					Enumerator<AIG_CoursePortal> enumerator2 = courseNode.m_portals.GetEnumerator();
					while (enumerator2.MoveNext())
					{
						AIG_CoursePortal current2 = enumerator2.Current;
						AIG_CourseNode oppositeNode = current2.GetOppositeNode(courseNode);
						int num4 = navData.nodeDistanceMap[oppositeNode.NodeID];
						val2 = current2.m_position - destination;
						float sqrMagnitude3 = ((Vector3)(ref val2)).sqrMagnitude;
						if (val4 == null || num4 < num2 || (num4 == num2 && sqrMagnitude3 < num3))
						{
							val4 = current2;
							num2 = num4;
							num3 = sqrMagnitude3;
						}
					}
					if (val4 != null)
					{
						if (targetPortal == null || ((Il2CppObjectBase)targetPortal).Pointer != ((Il2CppObjectBase)val4).Pointer)
						{
							targetPortal = val4;
							towardsPortalPosition = val4.RandomPositionOn_TowardsNode(courseNode);
							throughPortalPosition = val4.RandomPositionOn_TowardsNode(val4.GetOppositeNode(courseNode));
						}
						LG_Gate gate = val4.Gate;
						iLG_Door_Core val5 = ((gate != null) ? gate.SpawnedDoor : null);
						if (val5 != null)
						{
							if ((int)val5.LastStatus != 11 && (int)val5.LastStatus != 10 && (int)val5.LastStatus != 16)
							{
								((AgentAI)ai).m_navMeshAgent.destination = towardsPortalPosition;
								if (EB_InCombat_MoveToNextNode_DestroyDoor.s_globalRetryTimer < Clock.Time)
								{
									val2 = ((Agent)agent).m_position - towardsPortalPosition;
									if (((Vector3)(ref val2)).sqrMagnitude < 6.25f)
									{
										EB_InCombat_MoveToNextNode_DestroyDoor.s_globalRetryTimer = Clock.Time + Random.Range(0.5f, 1f);
										val5.AttemptDamage((eDoorDamageType)0, ((Agent)agent).m_position, (Agent)(object)agent);
									}
								}
								return;
							}
							if (num2 > 0)
							{
								((AgentAI)ai).m_navMeshAgent.destination = throughPortalPosition;
								return;
							}
						}
					}
				}
				else
				{
					targetPortal = null;
				}
			}
			((AgentAI)ai).m_navMeshAgent.destination = command.position;
		}

		private AIG_CourseNode? GetNode(Vector3 position)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			AIG_INode val = default(AIG_INode);
			AIG_NodeCluster val2 = default(AIG_NodeCluster);
			if (AIG_GeomorphNodeVolume.TryGetNode(0, Dimension.GetDimensionFromPos(position).DimensionIndex, position, ref val, false) && AIG_NodeCluster.TryGetNodeCluster(val.ClusterID, ref val2))
			{
				if (val2.CourseNode == null)
				{
					return null;
				}
				return val2.CourseNode;
			}
			return null;
		}

		private NavData GetNavData(AIG_CourseNode destination)
		{
			if (!navDataMap.ContainsKey(destination.NodeID))
			{
				NavData navData = new NavData();
				AIG_SearchID.IncrementSearchID();
				ushort searchID = AIG_SearchID.SearchID;
				Queue<(AIG_CourseNode, int)> queue = new Queue<(AIG_CourseNode, int)>();
				queue.Enqueue((destination, 0));
				((AIG_CourseGraphMember)destination).m_searchID = searchID;
				while (queue.Count > 0)
				{
					(AIG_CourseNode, int) tuple = queue.Dequeue();
					AIG_CourseNode item = tuple.Item1;
					int item2 = tuple.Item2;
					Enumerator<AIG_CoursePortal> enumerator = item.m_portals.GetEnumerator();
					while (enumerator.MoveNext())
					{
						AIG_CourseNode oppositeNode = enumerator.Current.GetOppositeNode(item);
						if (((AIG_CourseGraphMember)oppositeNode).m_searchID != searchID)
						{
							((AIG_CourseGraphMember)oppositeNode).m_searchID = searchID;
							queue.Enqueue((oppositeNode, item2 + 1));
						}
					}
					navData.nodeDistanceMap.Add(item.NodeID, item2);
				}
				navDataMap.Add(destination.NodeID, navData);
			}
			return navDataMap[destination.NodeID];
		}

		public static bool ChangeStatePrefix(StateMachine<EB_StateBase> __instance, EB_StateBase newState)
		{
			//IL_002b: 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_0048: Invalid comparison between Unknown and I4
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Invalid comparison between Unknown and I4
			EnemyController component = ((Component)__instance).GetComponent<EnemyController>();
			if ((Object)(object)component == (Object)null || !component.IsControlled)
			{
				return true;
			}
			Command command = component.commandBuffer.Peek();
			EB_States val = (EB_States)((MachineState<EB_StateBase>)(object)newState).ENUM_ID;
			switch (command.type)
			{
			case Command.Type.Move:
			case Command.Type.MoveAttack:
				if ((int)val == 8 || (int)val == 7)
				{
					return false;
				}
				break;
			}
			return true;
		}

		[ReplayInit]
		private static void Init()
		{
			APILogger.Debug("Clear old nav data.");
			navDataMap.Clear();
		}
	}
}
namespace MindControl.NativePatches
{
	internal static class ChangeStatePatches
	{
		private unsafe delegate void d_ChangeStateFromQueue(IntPtr _this, Il2CppMethodInfo* methodInfo);

		private static INativeDetour? ChangeStateDetour;

		private static d_ChangeStateFromQueue? orig_ChangeStateFromQueue;

		internal unsafe static void ApplyNativePatch()
		{
			NativePatchAPI.AddChangeStatePrefix(EnemyController.ChangeStatePrefix);
			INativeClassStruct val = UnityVersionHandler.Wrap((Il2CppClass*)(void*)Il2CppClassPointerStore<StateMachine<ES_Base>>.NativeClassPtr);
			for (int i = 0; i < val.MethodCount; i++)
			{
				INativeMethodInfoStruct val2 = UnityVersionHandler.Wrap(val.Methods[i]);
				if (Marshal.PtrToStringAnsi(val2.Name) == "ChangeStateFromQueue")
				{
					ChangeStateDetour = INativeDetour.CreateAndApply<d_ChangeStateFromQueue>(val2.MethodPointer, (d_ChangeStateFromQueue)ChangeStatePatch, ref orig_ChangeStateFromQueue);
					break;
				}
			}
		}

		private unsafe static void ChangeStatePatch(IntPtr _this, Il2CppMethodInfo* methodInfo)
		{
			StateMachine<EB_StateBase> val = new StateMachine<EB_StateBase>(_this);
			if (val.CurrentState == null)
			{
				orig_ChangeStateFromQueue(_this, methodInfo);
				return;
			}
			EB_StateBase state = val.m_stateQueue.Peek();
			bool flag = true;
			try
			{
				flag = NativePatchAPI.RunChangeStatePrefix(val, state);
			}
			catch (Exception ex)
			{
				APILogger.Error("Error running ChangeStatePrefix: " + ex.StackTrace);
			}
			if (flag)
			{
				orig_ChangeStateFromQueue(_this, methodInfo);
			}
			else
			{
				val.m_stateQueue.Dequeue();
			}
			try
			{
				NativePatchAPI.RunChangeStatePostfix(val, state);
			}
			catch (Exception ex2)
			{
				APILogger.Error("Error running ChangeStatePostfix: " + ex2.StackTrace);
			}
		}
	}
}
namespace MindControl.BepInEx
{
	public static class Module
	{
		public const string GUID = "randomuserhi.MindControl";

		public const string Name = "MindControl";

		public const string Version = "0.0.3";
	}
	public static class ConfigManager
	{
		public static ConfigFile configFile;

		private static ConfigEntry<bool> debug;

		public static bool Debug
		{
			get
			{
				return debug.Value;
			}
			set
			{
				debug.Value = value;
			}
		}

		static ConfigManager()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			configFile = new ConfigFile(Path.Combine(Paths.ConfigPath, "MindControl.cfg"), true);
			debug = configFile.Bind<bool>("Debug", "enable", false, "Enables debug messages when true.");
		}
	}
	[BepInPlugin("randomuserhi.MindControl", "MindControl", "0.0.3")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BasePlugin
	{
		private enum CommandType
		{
			MindControlPosition,
			MindControlClear,
			MindControlAttack,
			MindControlAttackPosition,
			MindControlKill
		}

		private static Harmony? harmony;

		public override void Load()
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			APILogger.Log("Plugin is loaded!");
			harmony = new Harmony("randomuserhi.MindControl");
			harmony.PatchAll();
			ClassInjector.RegisterTypeInIl2Cpp<EnemyController>();
			APILogger.Log("Debug is " + (ConfigManager.Debug ? "Enabled" : "Disabled"));
			VNet.Register("MindControl", (Action<ulong, ArraySegment<byte>>)OnMindControlCommand);
			VNet.Register("MindControl.SpawnEnemy", (Action<ulong, ArraySegment<byte>>)OnMindControlSpawnCommand);
		}

		private static AIG_CourseNode? GetNode(Vector3 position)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			AIG_INode val = default(AIG_INode);
			AIG_NodeCluster val2 = default(AIG_NodeCluster);
			if (AIG_GeomorphNodeVolume.TryGetNode(0, Dimension.GetDimensionFromPos(position).DimensionIndex, position, ref val, false) && AIG_NodeCluster.TryGetNodeCluster(val.ClusterID, ref val2))
			{
				if (val2.CourseNode == null)
				{
					return null;
				}
				return val2.CourseNode;
			}
			return null;
		}

		private static void OnMindControlSpawnCommand(ulong from, ArraySegment<byte> buffer)
		{
			//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_001f: 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)
			if (!SNet.IsMaster)
			{
				return;
			}
			int num = 0;
			Vector3 pos = BitHelper.ReadHalfVector3(buffer, ref num);
			Quaternion rot = Quaternion.identity;
			uint id = BitHelper.ReadUInt(buffer, ref num);
			MainThread.Run((Action)delegate
			{
				//IL_0001: 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_002e: Unknown result type (might be due to invalid IL or missing references)
				AIG_CourseNode val = GetNode(pos);
				if (val == null)
				{
					val = ((Agent)PlayerManager.GetLocalPlayerAgent()).CourseNode;
				}
				EnemyAllocator.Current.SpawnEnemy(id, val, (AgentMode)4, pos, rot, (EnemyGroup)null, -1);
			});
		}

		private static void OnMindControlCommand(ulong from, ArraySegment<byte> buffer)
		{
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			if (!SNet.IsMaster)
			{
				return;
			}
			int index = 0;
			CommandType commandType = (CommandType)BitHelper.ReadUShort(buffer, ref index);
			APILogger.Debug($"Received command of type '{commandType}'.");
			switch (commandType)
			{
			case CommandType.MindControlClear:
			{
				int numEnemies5 = BitHelper.ReadInt(buffer, ref index);
				APILogger.Debug($"Num Enemies '{numEnemies5}'.");
				MainThread.Run((Action)delegate
				{
					for (int i = 0; i < numEnemies5; i++)
					{
						ushort key = BitHelper.ReadUShort(buffer, ref index);
						if (EnemyController.controllers.TryGetValue(key, out EnemyController value) && value.commandBuffer.Count > 0)
						{
							value.ClearCommands();
						}
					}
				});
				break;
			}
			case CommandType.MindControlPosition:
			{
				Vector3 pos2 = BitHelper.ReadHalfVector3(buffer, ref index);
				int numEnemies4 = BitHelper.ReadInt(buffer, ref index);
				APILogger.Debug($"Num Enemies '{numEnemies4}'.");
				MainThread.Run((Action)delegate
				{
					//IL_006a: Unknown result type (might be due to invalid IL or missing references)
					for (int i = 0; i < numEnemies4; i++)
					{
						ushort key = BitHelper.ReadUShort(buffer, ref index);
						if (EnemyController.controllers.TryGetValue(key, out EnemyController value))
						{
							if (value.commandBuffer.Count > 0)
							{
								EnemyController.Command.Type type = value.commandBuffer.Peek().type;
								if (type == EnemyController.Command.Type.Move || type == EnemyController.Command.Type.MoveAttack)
								{
									value.commandBuffer.Clear();
								}
								else
								{
									value.ClearCommands();
								}
							}
							value.AddPosition(pos2);
						}
					}
				});
				break;
			}
			case CommandType.MindControlAttackPosition:
			{
				Vector3 pos = BitHelper.ReadHalfVector3(buffer, ref index);
				int numEnemies3 = BitHelper.ReadInt(buffer, ref index);
				APILogger.Debug($"Num Enemies '{numEnemies3}'.");
				MainThread.Run((Action)delegate
				{
					//IL_006a: Unknown result type (might be due to invalid IL or missing references)
					for (int i = 0; i < numEnemies3; i++)
					{
						ushort key = BitHelper.ReadUShort(buffer, ref index);
						if (EnemyController.controllers.TryGetValue(key, out EnemyController value))
						{
							if (value.commandBuffer.Count > 0)
							{
								EnemyController.Command.Type type = value.commandBuffer.Peek().type;
								if (type == EnemyController.Command.Type.Move || type == EnemyController.Command.Type.MoveAttack)
								{
									value.commandBuffer.Clear();
								}
								else
								{
									value.ClearCommands();
								}
							}
							value.AddAttackPosition(pos);
						}
					}
				});
				break;
			}
			case CommandType.MindControlAttack:
			{
				byte slot = BitHelper.ReadByte(buffer, ref index);
				int numEnemies2 = BitHelper.ReadInt(buffer, ref index);
				APILogger.Debug($"Num Enemies '{numEnemies2}'.");
				MainThread.Run((Action)delegate
				{
					if (slot < ((Il2CppArrayBase<SNet_Slot>)(object)SNet.Slots.PlayerSlots).Length)
					{
						PlayerAgent val = ((Il2CppObjectBase)((Il2CppArrayBase<SNet_Slot>)(object)SNet.Slots.PlayerSlots)[(int)slot].player.m_playerAgent).TryCast<PlayerAgent>();
						if ((Object)(object)val != (Object)null)
						{
							for (int i = 0; i < numEnemies2; i++)
							{
								ushort key = BitHelper.ReadUShort(buffer, ref index);
								if (EnemyController.controllers.TryGetValue(key, out EnemyController value))
								{
									if (value.commandBuffer.Count > 0)
									{
										if (value.commandBuffer.Peek().type == EnemyController.Command.Type.Attack)
										{
											value.commandBuffer.Clear();
										}
										else
										{
											value.ClearCommands();
										}
									}
									value.AddTarget(val);
								}
							}
						}
					}
				});
				break;
			}
			case CommandType.MindControlKill:
			{
				int numEnemies = BitHelper.ReadInt(buffer, ref index);
				APILogger.Debug($"Num Enemies '{numEnemies}'.");
				MainThread.Run((Action)delegate
				{
					for (int i = 0; i < numEnemies; i++)
					{
						ushort key = BitHelper.ReadUShort(buffer, ref index);
						if (EnemyController.controllers.TryGetValue(key, out EnemyController value))
						{
							value.Suicide();
						}
					}
				});
				break;
			}
			default:
				APILogger.Error($"No command defined for message of type '{commandType}'");
				break;
			}
		}
	}
}
namespace MindControl.API
{
	public static class NativePatchAPI
	{
		public delegate bool ChangeStatePrefix(StateMachine<EB_StateBase> __instance, EB_StateBase state);

		public delegate void ChangeStatePostfix(StateMachine<EB_StateBase> __instance, EB_StateBase state);

		private static readonly List<ChangeStatePrefix> s_changePrefix = new List<ChangeStatePrefix>();

		private static readonly List<ChangeStatePostfix> s_changePostfix = new List<ChangeStatePostfix>();

		public static void AddChangeStatePrefix(ChangeStatePrefix detectPrefix)
		{
			s_changePrefix.Add(detectPrefix);
		}

		public static void AddChangeStatePostfix(ChangeStatePostfix detectPostfix)
		{
			s_changePostfix.Add(detectPostfix);
		}

		internal static bool RunChangeStatePrefix(StateMachine<EB_StateBase> __instance, EB_StateBase state)
		{
			bool flag = true;
			foreach (ChangeStatePrefix item in s_changePrefix)
			{
				flag &= item(__instance, state);
			}
			return flag;
		}

		internal static void RunChangeStatePostfix(StateMachine<EB_StateBase> __instance, EB_StateBase state)
		{
			foreach (ChangeStatePostfix item in s_changePostfix)
			{
				item(__instance, state);
			}
		}
	}
}