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 Enemies; using HarmonyLib; using Il2CppInterop.Runtime.Injection; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppSystem.Collections.Generic; using LevelGeneration; using Microsoft.CodeAnalysis; using MindControl.BepInEx; using Player; using ReplayRecorder; using ReplayRecorder.Net; using SNetwork; using StateMachines; using UnityEngine; [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+91c81a4b4726217314e44288a66a576e540178aa")] [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() != (Object)null) && !agent.EnemyBehaviorData.IsFlyer) { ((Component)agent).gameObject.AddComponent().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; } } public class Command { public enum Type { Move, Attack, MoveAttack } public Type type; public PlayerAgent? target; public Vector3 position; public Vector3 destination; 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) //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) type = Type.Move; position = pos; destination = pos; } public Command(PlayerAgent target) { type = Type.Attack; this.target = target; } } public static Dictionary controllers = new Dictionary(); private int globalId; private EnemyAgent agent; private EnemyAI ai; private EnemyLocomotion locomotion; private EnemyBehaviour behaviour; private EnemyBehaviourData behaviourData; private EB_InCombat EBInCombat; public Queue commandBuffer = new Queue(); private PlayerAgent? currentTarget; 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)(object)behaviour).m_states[5]).Cast(); 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); Patches.DontRecurse = false; } } 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)(object)behaviour).m_currentState).TryCast() != 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_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Invalid comparison between Unknown and I4 //IL_0189: 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_018f: Invalid comparison between Unknown and I4 //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Invalid comparison between Unknown and I4 //IL_004f: 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_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_0191: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Invalid comparison between Unknown and I4 //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Invalid comparison between Unknown and I4 //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Invalid comparison between Unknown and I4 //IL_01e8: 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_01fd: 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_0205: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Invalid comparison between Unknown and I4 //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Unknown result type (might be due to invalid IL or missing references) //IL_023d: Invalid comparison between Unknown and I4 //IL_0227: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Invalid comparison between Unknown and I4 //IL_02ec: Unknown result type (might be due to invalid IL or missing references) //IL_0302: 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) Vector3 val; ES_StateEnum currentStateEnum; if (command.type == Command.Type.MoveAttack) { if ((Object)(object)currentTarget != (Object)null) { float max = agent.EnemyBehaviorData.MeleeAttackDistance.Max; float max2 = agent.EnemyBehaviorData.RangedAttackDistance.Max; val = ((Agent)currentTarget).m_position - ((Agent)agent).m_position; float sqrMagnitude = ((Vector3)(ref val)).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 enumerator = PlayerManager.PlayerAgentsInLevel.GetEnumerator(); while (enumerator.MoveNext()) { PlayerAgent current = enumerator.Current; if (current.m_alive) { val = ((Agent)current).m_position - ((Agent)agent).m_position; float sqrMagnitude2 = ((Vector3)(ref val)).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()) { return; } currentStateEnum = locomotion.CurrentStateEnum; if (currentStateEnum - 18 <= 1 || (int)currentStateEnum == 23) { return; } } } currentStateEnum = locomotion.CurrentStateEnum; if ((int)currentStateEnum <= 10) { if ((int)currentStateEnum == 7 || (int)currentStateEnum == 10) { return; } } else if (currentStateEnum - 24 <= 1 || (int)currentStateEnum == 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; val = command.destination - ((Component)ai).transform.position; ((Agent)enemyAgent).TargetLookDir = ((Vector3)(ref val)).normalized; } else { ((Agent)ai.m_enemyAgent).TargetLookDir = ((AgentAI)ai).m_target.m_dir; } if ((int)locomotion.CurrentStateEnum != 2) { locomotion.ChangeState((ES_StateEnum)2); } if (((Il2CppObjectBase)((StateMachine)(object)behaviour).m_currentState).TryCast() == null) { Patches.DontRecurse = true; behaviour.ChangeState((EB_States)5); behaviour.m_updatebehaviour = 0f; ((StateMachine)(object)behaviour).UpdateState(); behaviour.ChangeState((EB_States)7); behaviour.m_updatebehaviour = 0f; ((StateMachine)(object)behaviour).UpdateState(); behaviour.ChangeState((EB_States)6); Patches.DontRecurse = false; } EBInCombat.UpdateAvoidance(); if (((AgentAI)ai).m_navMeshAgent.isOnNavMesh) { ((AgentAI)ai).m_navMeshAgent.destination = command.position; command.destination = ((AgentAI)ai).m_navMeshAgent.destination; } } } } namespace MindControl.BepInEx { public static class Module { public const string GUID = "randomuserhi.MindControl"; public const string Name = "MindControl"; public const string Version = "0.0.1"; } public static class ConfigManager { public static ConfigFile configFile; private static ConfigEntry 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("Debug", "enable", false, "Enables debug messages when true."); } } [BepInPlugin("randomuserhi.MindControl", "MindControl", "0.0.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BasePlugin { private enum CommandType { MindControlPosition, MindControlClear, MindControlAttack, MindControlAttackPosition } 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(); APILogger.Log("Debug is " + (ConfigManager.Debug ? "Enabled" : "Disabled")); VNet.Register("MindControl", (Action>)OnMindControlCommand); VNet.Register("MindControl.SpawnEnemy", (Action>)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 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 buffer) { //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: 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 numEnemies4 = BitHelper.ReadInt(buffer, ref index); APILogger.Debug($"Num Enemies '{numEnemies4}'."); MainThread.Run((Action)delegate { for (int i = 0; i < numEnemies4; i++) { ushort key = BitHelper.ReadUShort(buffer, ref index); if (EnemyController.controllers.TryGetValue(key, out EnemyController value)) { value.ClearCommands(); } } }); break; } case CommandType.MindControlPosition: { Vector3 pos2 = BitHelper.ReadHalfVector3(buffer, ref index); int numEnemies3 = BitHelper.ReadInt(buffer, ref index); APILogger.Debug($"Num Enemies '{numEnemies3}'."); MainThread.Run((Action)delegate { //IL_0037: 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)) { value.ClearCommands(); value.AddPosition(pos2); } } }); break; } case CommandType.MindControlAttackPosition: { Vector3 pos = BitHelper.ReadHalfVector3(buffer, ref index); int numEnemies2 = BitHelper.ReadInt(buffer, ref index); APILogger.Debug($"Num Enemies '{numEnemies2}'."); MainThread.Run((Action)delegate { //IL_0037: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < numEnemies2; i++) { ushort key = BitHelper.ReadUShort(buffer, ref index); if (EnemyController.controllers.TryGetValue(key, out EnemyController value)) { value.ClearCommands(); value.AddAttackPosition(pos); } } }); break; } case CommandType.MindControlAttack: { byte slot = BitHelper.ReadByte(buffer, ref index); int numEnemies = BitHelper.ReadInt(buffer, ref index); APILogger.Debug($"Num Enemies '{numEnemies}'."); MainThread.Run((Action)delegate { if (slot < ((Il2CppArrayBase)(object)SNet.Slots.PlayerSlots).Length) { PlayerAgent val = ((Il2CppObjectBase)((Il2CppArrayBase)(object)SNet.Slots.PlayerSlots)[(int)slot].player.m_playerAgent).TryCast(); if ((Object)(object)val != (Object)null) { for (int i = 0; i < numEnemies; i++) { ushort key = BitHelper.ReadUShort(buffer, ref index); if (EnemyController.controllers.TryGetValue(key, out EnemyController value)) { value.ClearCommands(); value.AddTarget(val); } } } } }); break; } default: APILogger.Error($"No command defined for message of type '{commandType}'"); break; } } } }