Decompiled source of ControlCompany v1.3.4

ControlCompany.dll

Decompiled 6 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ControlCompany.Core;
using ControlCompany.Core.Config;
using ControlCompany.Core.Enemy;
using ControlCompany.Core.Enemy.NonStandardEnemy;
using ControlCompany.Core.Extentions;
using ControlCompany.Core.Input;
using ControlCompany.Core.UI;
using ControlCompany.Patches;
using Dissonance;
using GameNetcodeStuff;
using HarmonyLib;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.Rendering.HighDefinition;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("ControlCompany")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ControlCompany")]
[assembly: AssemblyCopyright("Copyright ©  2024")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("dfed064e-ab44-4aa7-b361-7a59370d39a8")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace ControlCompany
{
	[BepInPlugin("ControlCompany.ControlCompany", "ControlCompany", "1.3.2")]
	public class ControlCompanyPlugin : BaseUnityPlugin
	{
		private const string modGUID = "ControlCompany.ControlCompany";

		private const string modName = "ControlCompany";

		private const string modVersion = "1.3.2";

		private readonly Harmony harmony = new Harmony("ControlCompany.ControlCompany");

		public static ControlCompanyPlugin Instance;

		internal ManualLogSource logger;

		private bool isInitialized = false;

		private bool ranInitializationScripts = false;

		private void Awake()
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Expected O, but got Unknown
			if ((Object)(object)Instance == (Object)null)
			{
				Instance = this;
			}
			logger = Logger.CreateLogSource("ControlCompany.ControlCompany");
			logger.LogInfo((object)"Loaded ControlCompany. Patching.");
			ApplyPatches();
			logger.LogInfo((object)"Completed patching. Initializing.");
			GameObject val = new GameObject("control_company_config_manager");
			val.AddComponent<ConfigManager>();
			((Object)val).hideFlags = (HideFlags)61;
			Object.DontDestroyOnLoad((Object)(object)val);
			logger.LogInfo((object)"Completed initialization.");
			isInitialized = true;
		}

		private void ApplyPatches()
		{
			harmony.PatchAll(typeof(ControlCompanyPlugin));
			harmony.PatchAll(typeof(HUDManagerPatch));
			harmony.PatchAll(typeof(StartOfRoundPatch));
			harmony.PatchAll(typeof(PlayerControllerBPatch));
			harmony.PatchAll(typeof(EnemyAIPatch));
			harmony.PatchAll(typeof(TimeOfDayPatch));
			harmony.PatchAll(typeof(SoundManagerPatch));
			harmony.PatchAll(typeof(LobbyListPatch));
		}
	}
}
namespace ControlCompany.Patches
{
	[HarmonyPatch(typeof(EnemyAI))]
	internal class EnemyAIPatch
	{
		[HarmonyPatch("ChangeOwnershipOfEnemy")]
		[HarmonyPrefix]
		private static bool ChangeOwnershipOfEnemyPrefix(EnemyAI __instance, ref ulong newOwnerClientId)
		{
			if ((Object)(object)ControlCenter.Instance != (Object)null && ControlCenter.Instance.CurrentMode == ControlCenter.Mode.ENEMY)
			{
				if ((Object)(object)ControlCenter.Instance.CurrentControlledEnemy != (Object)null)
				{
					ulong actualClientId = ControlCenter.Instance.GetHostPlayer().actualClientId;
					bool flag = actualClientId == newOwnerClientId || ControlCenter.Instance.CurrentControlledEnemy.IsAIControlled;
					EnemyController currentControlledEnemy = ControlCenter.Instance.CurrentControlledEnemy;
					if (((object)currentControlledEnemy).GetType() == typeof(EnemyAIController))
					{
						EnemyAIController enemyAIController = (EnemyAIController)ControlCenter.Instance.CurrentControlledEnemy;
						flag = flag || (Object)(object)enemyAIController.EnemyAI != (Object)(object)__instance;
					}
					return flag;
				}
				return true;
			}
			return true;
		}

		[HarmonyPatch("ChangeEnemyOwnerServerRpc")]
		[HarmonyPrefix]
		private static bool ChangeEnemyOwnerServerRpcPrefix(EnemyAI __instance, ref ulong clientId)
		{
			if ((Object)(object)ControlCenter.Instance != (Object)null && ControlCenter.Instance.CurrentMode == ControlCenter.Mode.ENEMY)
			{
				if ((Object)(object)ControlCenter.Instance.CurrentControlledEnemy != (Object)null)
				{
					ulong actualClientId = ControlCenter.Instance.GetHostPlayer().actualClientId;
					bool flag = actualClientId == clientId || ControlCenter.Instance.CurrentControlledEnemy.IsAIControlled;
					EnemyController currentControlledEnemy = ControlCenter.Instance.CurrentControlledEnemy;
					if (((object)currentControlledEnemy).GetType() == typeof(EnemyAIController))
					{
						EnemyAIController enemyAIController = (EnemyAIController)ControlCenter.Instance.CurrentControlledEnemy;
						flag = flag || (Object)(object)enemyAIController.EnemyAI != (Object)(object)__instance;
					}
					return flag;
				}
				return true;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(HUDManager))]
	internal class HUDManagerPatch
	{
		[HarmonyPatch("CanPlayerScan")]
		[HarmonyPostfix]
		private static void CanPlayerScanPostfix(ref bool __result)
		{
			if (__result && (Object)(object)ControlCenter.Instance != (Object)null)
			{
				__result = ControlCenter.Instance.CurrentMode == ControlCenter.Mode.HOST;
			}
		}

		[HarmonyPatch("UpdateHealthUI")]
		[HarmonyPrefix]
		private static bool UpdateHealthUIPrefix()
		{
			if ((Object)(object)ControlCenter.Instance != (Object)null)
			{
				return ControlCenter.Instance.CurrentMode == ControlCenter.Mode.HOST;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(PlayerControllerB))]
	internal class PlayerControllerBPatch
	{
		[HarmonyPatch("PlayerLookInput")]
		[HarmonyPrefix]
		private static bool PlayerLookInputPrefix()
		{
			if ((Object)(object)ControlCenter.Instance != (Object)null)
			{
				return ControlCenter.Instance.CurrentMode == ControlCenter.Mode.HOST;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(SoundManager))]
	internal class SoundManagerPatch
	{
		[HarmonyPatch("SetEarsRinging")]
		[HarmonyPrefix]
		private static bool SetEarsRingingPrefix()
		{
			if ((Object)(object)ControlCenter.Instance != (Object)null)
			{
				return ControlCenter.Instance.CurrentMode == ControlCenter.Mode.HOST;
			}
			return true;
		}
	}
	internal class StartOfRoundPatch
	{
		[HarmonyPatch(typeof(StartOfRound), "ShipHasLeft")]
		[HarmonyPrefix]
		private static void ShipHasLeftPrefix()
		{
			if ((Object)(object)ControlCenter.Instance != (Object)null)
			{
				ControlCenter.Instance.EndOfRoundCleanUp();
			}
		}

		[HarmonyPatch(typeof(RoundManager), "RefreshEnemiesList")]
		[HarmonyPostfix]
		private static void StartGamePostfix()
		{
			if ((Object)(object)ControlCenter.Instance != (Object)null)
			{
				ControlCenter.Instance.StartOfRoundInitialization();
			}
		}

		[HarmonyPatch(typeof(StartOfRound), "Awake")]
		[HarmonyPostfix]
		private static void CreateControlCenter()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			if (!ConfigManager.Instance.DisableModForSelf)
			{
				GameObject val = new GameObject("control_company_control_center");
				val.AddComponent<ControlCenter>();
				val.AddComponent<UIManager>();
			}
		}
	}
	internal class LobbyListPatch
	{
		public const char SERVER_NAME_FILTER = '\u200b';
	}
	[HarmonyPatch(typeof(TimeOfDay))]
	internal class TimeOfDayPatch
	{
		[HarmonyPatch("VoteShipToLeaveEarly")]
		[HarmonyPrefix]
		private static bool VoteToLeaveEarly()
		{
			if ((Object)(object)ControlCenter.Instance != (Object)null)
			{
				return ControlCenter.Instance.CurrentMode == ControlCenter.Mode.HOST;
			}
			return true;
		}
	}
}
namespace ControlCompany.Core
{
	internal static class Constants
	{
		public static Dictionary<int, string> ALL_LAYERS_DICT = (from index in Enumerable.Range(0, 32)
			where !string.IsNullOrEmpty(LayerMask.LayerToName(index))
			select index).ToDictionary((int index) => index, (int index) => LayerMask.LayerToName(index));

		public static string PLAYER_LOS_LAYERNAME = "LineOfSight";

		public static int PLAYER_LOS_LAYERINDEX = LayerMask.NameToLayer(PLAYER_LOS_LAYERNAME);

		public static LayerMask PLAYER_LOS_LAYERMASK = LayerMask.op_Implicit(LayerMask.GetMask(new string[1] { PLAYER_LOS_LAYERNAME }));

		public static string PLAYER_LAYERNAME = "Player";

		public static int PLAYER_LAYERINDEX = LayerMask.NameToLayer(PLAYER_LAYERNAME);

		public static LayerMask PLAYER_LAYERMASK = LayerMask.op_Implicit(LayerMask.GetMask(new string[1] { PLAYER_LAYERNAME }));

		public static string PLAYER_VISOR_LAYERNAME = "HelmetVisor";

		public static int PLAYER_VISOR_LAYERINDEX = LayerMask.NameToLayer(PLAYER_VISOR_LAYERNAME);

		public static LayerMask PLAYER_VISOR_LAYERMASK = LayerMask.op_Implicit(LayerMask.GetMask(new string[1] { PLAYER_VISOR_LAYERNAME }));

		public static string ITERACTABLE_OBJ_LAYERNAME = "InteractableObject";

		public static int ITERACTABLE_OBJ_LAYERINDEX = LayerMask.NameToLayer(ITERACTABLE_OBJ_LAYERNAME);

		public static LayerMask ITERACTABLE_OBJ_LAYERMASK = LayerMask.op_Implicit(LayerMask.GetMask(new string[1] { ITERACTABLE_OBJ_LAYERNAME }));

		public static string PROPS_OBJ_LAYERNAME = "Props";

		public static int PROPS_OBJ_LAYERINDEX = LayerMask.NameToLayer(PROPS_OBJ_LAYERNAME);

		public static LayerMask PROPS_LAYERMASK = LayerMask.op_Implicit(LayerMask.GetMask(new string[1] { PROPS_OBJ_LAYERNAME }));

		public static string ENEMIES_OBJ_LAYERNAME = "Enemies";

		public static int ENEMIES_OBJ_LAYERINDEX = LayerMask.NameToLayer(ENEMIES_OBJ_LAYERNAME);

		public static LayerMask ENEMIES_LAYERMASK = LayerMask.op_Implicit(LayerMask.GetMask(new string[1] { ENEMIES_OBJ_LAYERNAME }));

		public static string PLAYER_RAGDOLL_LAYERNAME = "PlayerRagdoll";

		public static int PLAYER_RAGDOLL_LAYERINDEX = LayerMask.NameToLayer(PLAYER_RAGDOLL_LAYERNAME);

		public static LayerMask PLAYER_RAGDOLL_LAYERMASK = LayerMask.op_Implicit(LayerMask.GetMask(new string[1] { PLAYER_RAGDOLL_LAYERNAME }));

		public static string PHYSICS_OBJECT_LAYERNAME = "PhysicsObject";

		public static int PHYSICS_OBJECT_LAYERINDEX = LayerMask.NameToLayer(PHYSICS_OBJECT_LAYERNAME);

		public static LayerMask PHYSICS_OBJECT_LAYERMASK = LayerMask.op_Implicit(LayerMask.GetMask(new string[1] { PHYSICS_OBJECT_LAYERNAME }));
	}
	internal class ControlCenter : MonoBehaviour
	{
		public enum Mode
		{
			HOST,
			GHOST,
			ENEMY
		}

		public static ControlCenter Instance;

		private CustomPlayerController ghostController;

		private GameObject ghost;

		private EnemyController currentControlledEnemy;

		private int currentTargetIndex = 0;

		private PlayerControllerB currentTarget;

		private Mode currentMode = Mode.HOST;

		private bool allowAllEnemies = false;

		private bool initialMicPushToTalkSetting = false;

		private bool isExtendedModeEnabled = false;

		private bool scrapSpawnMode = false;

		private int currentSpawnScrapPage = 0;

		private const int scrapSpawnPageSize = 10;

		private int currentSpawnEnemiesPage = 0;

		private const int spawnEnemiesPageSize = 12;

		private List<ControllableEnemy> currentSpawnableEnemyList = new List<ControllableEnemy>();

		private bool loadedConfig = false;

		private bool showUI = true;

		private float gameStartedTime = 0f;

		private bool inRoundEndPhase = false;

		private bool isGhostIndoors = false;

		private List<ControllableEnemy> allIndoorEnemies = new List<ControllableEnemy>();

		private List<ControllableEnemy> allOutdoorEnemies = new List<ControllableEnemy>();

		private List<ControllableEnemy> indoorEnemiesOfLevel = new List<ControllableEnemy>();

		private List<ControllableEnemy> outdoorEnemiesOfLevel = new List<ControllableEnemy>();

		public Mode CurrentMode => currentMode;

		public EnemyController CurrentControlledEnemy => currentControlledEnemy;

		public bool IsGhostIndoors
		{
			get
			{
				return isGhostIndoors;
			}
			set
			{
				isGhostIndoors = value;
			}
		}

		private void Awake()
		{
			if ((Object)(object)Instance == (Object)null)
			{
				Instance = this;
			}
		}

		private void OnEnable()
		{
			if (!loadedConfig)
			{
				loadedConfig = true;
				ConfigManager.Instance.LoadPlayerConfig(reload: true);
			}
		}

		private void Update()
		{
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Expected O, but got Unknown
			if (!IsGameStarted())
			{
				return;
			}
			if (((ButtonControl)InputKeys.TOGGLE_UI_KEY).wasPressedThisFrame)
			{
				showUI = !showUI;
			}
			gameStartedTime += Time.deltaTime;
			if (!IsHost() || inRoundEndPhase)
			{
				return;
			}
			if (((Object)(object)currentTarget == (Object)null || !currentTarget.isPlayerControlled || currentTarget.isPlayerDead) && GetAlivePlayers().Count > 0)
			{
				SetNextTargetPlayer(1);
			}
			if ((Object)(object)ghost == (Object)null)
			{
				GameObject val = new GameObject("ghost");
				ghostController = val.AddComponent<CustomPlayerController>();
				ghostController.Initialize(GetHostPlayer().playerActions, CustomPlayerController.CameraMode.FIRST_PERSON);
				ghost = val;
				ghost.SetActive(false);
				ControlCompanyPlugin.Instance.logger.LogInfo((object)"Creating ghost");
			}
			if (currentMode != 0)
			{
				GetHostPlayer().isTypingChat = true;
			}
			if (IsListeningFromHost() && !IsHostDead() && currentMode != 0)
			{
				if ((Object)(object)ghostController != (Object)null)
				{
					((Behaviour)ghostController.AudioListener).enabled = false;
				}
				if ((Object)(object)currentControlledEnemy != (Object)null)
				{
					((Behaviour)currentControlledEnemy.AudioListener).enabled = false;
				}
				((Behaviour)GetHostPlayer().activeAudioListener).enabled = true;
				ChangeAudioListener(GetHostPlayer().activeAudioListener);
			}
			else if (currentMode == Mode.GHOST)
			{
				if ((Object)(object)ghostController != (Object)null && ghostController.IsInitialized)
				{
					((Behaviour)GetHostPlayer().activeAudioListener).enabled = false;
					((Behaviour)ghostController.AudioListener).enabled = true;
					ChangeAudioListener(ghostController.AudioListener);
				}
			}
			else if (currentMode == Mode.ENEMY)
			{
				if (((Object)(object)currentControlledEnemy != (Object)null) & currentControlledEnemy.IsInitialized)
				{
					((Behaviour)GetHostPlayer().activeAudioListener).enabled = false;
					((Behaviour)currentControlledEnemy.AudioListener).enabled = true;
					ChangeAudioListener(currentControlledEnemy.AudioListener);
				}
			}
			else if (currentMode == Mode.HOST)
			{
				ChangeAudioListener(GetHostPlayer().activeAudioListener);
			}
			InputUpdate();
		}

		private void InputUpdate()
		{
			//IL_0231: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_05a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_04fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_047a: Unknown result type (might be due to invalid IL or missing references)
			//IL_048a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0415: Unknown result type (might be due to invalid IL or missing references)
			//IL_0425: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ec: Unknown result type (might be due to invalid IL or missing references)
			if (!IsGameStarted() || !IsHost() || inRoundEndPhase || (ConfigManager.Instance.DisableWhileUsingTerminal && GetHostPlayer().inTerminalMenu))
			{
				return;
			}
			if (((ButtonControl)InputKeys.EXTENDED_MODE_KEY).wasPressedThisFrame)
			{
				isExtendedModeEnabled = !isExtendedModeEnabled;
				allowAllEnemies = isExtendedModeEnabled;
				SetNextSpawnEnemiesPage(0);
			}
			switch (currentMode)
			{
			case Mode.ENEMY:
				if (!currentControlledEnemy.IsAIControlled && currentControlledEnemy.CanControlEnemy())
				{
					if (InputKeys.ENEMY_PRIMARY_SKILL_BUTTON.wasPressedThisFrame)
					{
						currentControlledEnemy.UsePrimarySkill();
					}
					else if (InputKeys.ENEMY_PRIMARY_SKILL_BUTTON.wasReleasedThisFrame)
					{
						currentControlledEnemy.ReleasePrimarySkill();
					}
					else if (InputKeys.ENEMY_SECONDARY_SKILL_BUTTON.wasPressedThisFrame)
					{
						currentControlledEnemy.UseSecondarySkill();
					}
					else if (InputKeys.ENEMY_SECONDARY_SKILL_BUTTON.wasReleasedThisFrame)
					{
						currentControlledEnemy.ReleaseSecondarySkill();
					}
					currentControlledEnemy.SetLockEnemyRotation(((ButtonControl)InputKeys.LOCK_ENEMY_ROTATION_KEY).isPressed);
				}
				if (((ButtonControl)InputKeys.EXIT_KEY).wasPressedThisFrame)
				{
					EnableGhost(enable: true, ((Component)currentControlledEnemy).transform.position);
					ghostController.EnableLight(isGhostIndoors);
					currentControlledEnemy.DestroyAndCleanUp();
					currentMode = Mode.GHOST;
				}
				else if (((ButtonControl)InputKeys.ENEMY_TOGGLE_AI_KEY).wasPressedThisFrame)
				{
					currentControlledEnemy.ToggleAIControl();
				}
				else if (((ButtonControl)InputKeys.ENEMY_TOGGLE_LIGHT_KEY).wasPressedThisFrame)
				{
					currentControlledEnemy.ToggleLight();
				}
				break;
			case Mode.HOST:
				if (((ButtonControl)InputKeys.HOST_GHOST_MODE_KEY).wasPressedThisFrame)
				{
					isGhostIndoors = IsTargetInside();
					EnableGhost(enable: true, ((Component)currentTarget).gameObject.transform.position);
					ghostController.EnableLight(isGhostIndoors);
					EnableHostPlayer(enable: false);
					currentMode = Mode.GHOST;
				}
				else if (((ButtonControl)InputKeys.CYCLE_KEY_LEFT).wasPressedThisFrame)
				{
					SetNextTargetPlayer(-1);
				}
				else if (((ButtonControl)InputKeys.CYCLE_KEY_RIGHT).wasPressedThisFrame)
				{
					SetNextTargetPlayer(1);
				}
				if (!isExtendedModeEnabled)
				{
					break;
				}
				if (((ButtonControl)InputKeys.HOST_TELEPORT_TO_ENTRANCE_KEY).wasPressedThisFrame)
				{
					if (!GetHostPlayer().isPlayerDead)
					{
						EntranceTeleport mainEntrance = GetMainEntrance(getMainEntranceThatIsOutside: true);
						if ((Object)(object)mainEntrance != (Object)null)
						{
							mainEntrance.TeleportPlayer();
						}
					}
				}
				else if (((ButtonControl)InputKeys.HOST_GIVE_CREDITS_KEY).wasPressedThisFrame)
				{
					Terminal obj = Object.FindObjectOfType<Terminal>();
					obj.groupCredits += 100;
				}
				break;
			case Mode.GHOST:
				if (!scrapSpawnMode)
				{
					List<ControllableEnemy> pagedSpawnableEnemies = GetPagedSpawnableEnemies();
					for (int i = 0; i < InputKeys.GHOST_SPAWN_ENEMY_KEYS.Count && i < pagedSpawnableEnemies.Count; i++)
					{
						if (!((ButtonControl)InputKeys.GHOST_SPAWN_ENEMY_KEYS[i]).wasPressedThisFrame)
						{
							continue;
						}
						if (ConfigManager.Instance.UseEnemySpawningBehaviour)
						{
							Random random = new Random(StartOfRound.Instance.randomMapSeed + 888);
							if (isGhostIndoors)
							{
								RoundManager.Instance.RefreshEnemyVents();
								EnemyVent[] allEnemyVents = RoundManager.Instance.allEnemyVents;
								if (allEnemyVents.Count() > 0)
								{
									EnemyVent val = allEnemyVents[random.Next(allEnemyVents.Count())];
									currentControlledEnemy = SpawnControllableEnemy(pagedSpawnableEnemies[i], val.floorNode.position, val.floorNode.rotation);
								}
								else
								{
									currentControlledEnemy = SpawnControllableEnemy(pagedSpawnableEnemies[i], ghost.transform.position, ghost.transform.rotation);
								}
							}
							else
							{
								GameObject[] array = GameObject.FindGameObjectsWithTag("OutsideAINode");
								if (array.Count() > 0)
								{
									currentControlledEnemy = SpawnControllableEnemy(pagedSpawnableEnemies[i], array[random.Next(array.Count())].transform.position, ghost.transform.rotation);
								}
								else
								{
									currentControlledEnemy = SpawnControllableEnemy(pagedSpawnableEnemies[i], ghost.transform.position, ghost.transform.rotation);
								}
							}
						}
						else
						{
							currentControlledEnemy = SpawnControllableEnemy(pagedSpawnableEnemies[i], ghost.transform.position, ghost.transform.rotation);
						}
						EnableGhost(enable: false);
						currentMode = Mode.ENEMY;
						break;
					}
				}
				else
				{
					List<Item> list = ExtensionMethods.Chunk(GetSpawnableScraps(), 10).ToList()[currentSpawnScrapPage].ToList();
					for (int j = 0; j < InputKeys.GHOST_SPAWN_ENEMY_KEYS.Count && j < list.Count; j++)
					{
						if (((ButtonControl)InputKeys.GHOST_SPAWN_ENEMY_KEYS[j]).wasPressedThisFrame)
						{
							SpawnScrap(list[j], ghost.transform.position);
							break;
						}
					}
				}
				if (((ButtonControl)InputKeys.EXIT_KEY).wasPressedThisFrame)
				{
					EnableGhost(enable: false);
					EnableHostPlayer(enable: true);
					currentMode = Mode.HOST;
					GetHostPlayer().isTypingChat = false;
				}
				else if (((ButtonControl)InputKeys.CYCLE_KEY_LEFT).wasPressedThisFrame)
				{
					SetNextSpawnEnemiesPage(-1);
				}
				else if (((ButtonControl)InputKeys.CYCLE_KEY_RIGHT).wasPressedThisFrame)
				{
					SetNextSpawnEnemiesPage(1);
				}
				if (((ButtonControl)Keyboard.current.upArrowKey).wasPressedThisFrame)
				{
				}
				if (scrapSpawnMode && ((ButtonControl)Keyboard.current.downArrowKey).wasPressedThisFrame)
				{
					int num = Mathf.CeilToInt((float)GetSpawnableScraps().Count / 10f);
					ControlCompanyPlugin.Instance.logger.LogMessage((object)$"Total scraps: {GetSpawnableScraps().Count()}, final page of scrap: {num}");
					currentSpawnScrapPage++;
					if (currentSpawnScrapPage >= num)
					{
						currentSpawnScrapPage = 0;
					}
				}
				break;
			}
		}

		private void ChangeAudioListener(AudioListener audioListener)
		{
			StartOfRound.Instance.audioListener = audioListener;
		}

		private EntranceTeleport GetMainEntrance(bool getMainEntranceThatIsOutside)
		{
			EntranceTeleport[] array = Object.FindObjectsOfType<EntranceTeleport>(false);
			foreach (EntranceTeleport val in array)
			{
				if (val.entranceId != 0)
				{
					continue;
				}
				if (getMainEntranceThatIsOutside)
				{
					if (val.isEntranceToBuilding)
					{
						return val;
					}
				}
				else if (!val.isEntranceToBuilding)
				{
					return val;
				}
			}
			return null;
		}

		private bool IsTargetInside()
		{
			return (Object)(object)currentTarget != (Object)null && currentTarget.isInsideFactory;
		}

		private void OnGUI()
		{
			if (!IsGameStarted() || !showUI)
			{
				return;
			}
			if (!IsHost())
			{
				if (gameStartedTime < 30f)
				{
					UIManager.Instance.RenderNotHostLabel(((InputControl)InputKeys.TOGGLE_UI_KEY).displayName);
				}
			}
			else
			{
				if (inRoundEndPhase || (ConfigManager.Instance.DisableWhileUsingTerminal && GetHostPlayer().inTerminalMenu))
				{
					return;
				}
				switch (currentMode)
				{
				case Mode.ENEMY:
					UIManager.Instance.RenderEnemyControls(((InputControl)InputKeys.ENEMY_PRIMARY_SKILL_BUTTON).shortDisplayName, ((InputControl)InputKeys.ENEMY_SECONDARY_SKILL_BUTTON).shortDisplayName, ((InputControl)InputKeys.ENEMY_TOGGLE_AI_KEY).displayName, ((InputControl)InputKeys.EXIT_KEY).displayName, ((InputControl)InputKeys.HOST_LISTEN_KEY).displayName, currentControlledEnemy, GetHostPlayer());
					break;
				case Mode.HOST:
					UIManager.Instance.RenderHostControls(((InputControl)InputKeys.HOST_GHOST_MODE_KEY).displayName, ((InputControl)InputKeys.CYCLE_KEY_LEFT).displayName, ((InputControl)InputKeys.CYCLE_KEY_RIGHT).displayName, currentTarget, isExtendedModeEnabled, ((InputControl)InputKeys.HOST_GIVE_CREDITS_KEY).displayName, ((InputControl)InputKeys.HOST_TELEPORT_TO_ENTRANCE_KEY).displayName, ((InputControl)InputKeys.TOGGLE_UI_KEY).displayName);
					break;
				case Mode.GHOST:
				{
					bool showEnemyPaging = GetSpawnableEnemies(isGhostIndoors).Count > 12;
					List<IEnumerable<Item>> list = ExtensionMethods.Chunk(GetSpawnableScraps(), 10).ToList();
					List<Item> scraps = ((list.Count > 0) ? list[currentSpawnScrapPage].ToList() : new List<Item>());
					UIManager.Instance.RenderGhostControls(InputKeys.GHOST_SPAWN_ENEMY_KEYS.Select((KeyControl key) => ((InputControl)key).displayName).ToList(), ((InputControl)InputKeys.EXIT_KEY).displayName, ((InputControl)InputKeys.CYCLE_KEY_LEFT).displayName, ((InputControl)InputKeys.CYCLE_KEY_RIGHT).displayName, ((InputControl)InputKeys.HOST_LISTEN_KEY).displayName, showEnemyPaging, GetPagedSpawnableEnemies(), scraps, GetHostPlayer(), scrapSpawnMode);
					break;
				}
				}
			}
		}

		private bool IsHostDead()
		{
			return GetHostPlayer().isPlayerDead;
		}

		private void EnableGhost(bool enable)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			EnableGhost(enable, Vector3.zero);
		}

		private void EnableGhost(bool enable, Vector3 position)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			if (enable)
			{
				ghost.transform.position = position + new Vector3(0f, 0.5f, 0f);
				ghost.transform.rotation = Quaternion.identity;
				ghost.SetActive(true);
				ChangeAudioListener(ghostController.AudioListener);
				SetNextSpawnEnemiesPage(0);
			}
			else
			{
				ghost.SetActive(false);
			}
		}

		private void EnableHostPlayer(bool enable)
		{
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			PlayerControllerB hostPlayer = GetHostPlayer();
			MovementActions movement;
			if (enable)
			{
				if (ConfigManager.Instance.ForcePushToTalkWhileInMonsterMode)
				{
					ResetMicPushToTalk();
				}
				((Behaviour)GetHostPlayer().activeAudioListener).enabled = true;
				movement = hostPlayer.playerActions.Movement;
				((MovementActions)(ref movement)).PingScan.Enable();
				ChangeAudioListener(hostPlayer.activeAudioListener);
				((Behaviour)StartOfRound.Instance.activeCamera).enabled = true;
			}
			else
			{
				if (ConfigManager.Instance.ForcePushToTalkWhileInMonsterMode)
				{
					ForceMicPushToTalk();
				}
				((Behaviour)GetHostPlayer().activeAudioListener).enabled = false;
				movement = hostPlayer.playerActions.Movement;
				((MovementActions)(ref movement)).PingScan.Disable();
				((Behaviour)StartOfRound.Instance.activeCamera).enabled = false;
			}
		}

		private void EnablePlayer2DMics(bool enable, List<PlayerControllerB> players)
		{
			foreach (PlayerControllerB player in players)
			{
				if (player.isHostPlayerObject)
				{
					continue;
				}
				AudioSource currentVoiceChatAudioSource = player.currentVoiceChatAudioSource;
				if (enable)
				{
					if ((Object)(object)currentVoiceChatAudioSource != (Object)null)
					{
						currentVoiceChatAudioSource.spatialBlend = 0f;
					}
					player.currentVoiceChatIngameSettings.set2D = true;
					player.voicePlayerState.Volume = 1f;
				}
				else
				{
					if ((Object)(object)currentVoiceChatAudioSource != (Object)null)
					{
						currentVoiceChatAudioSource.spatialBlend = 1f;
					}
					player.currentVoiceChatIngameSettings.set2D = false;
					player.voicePlayerState.Volume = 0f;
				}
			}
		}

		private void SetNextTargetPlayer(int direction)
		{
			List<PlayerControllerB> alivePlayers = GetAlivePlayers();
			if (alivePlayers.Count == 0)
			{
				SetCurrentTargetToHost();
				ControlCompanyPlugin.Instance.logger.LogMessage((object)"Alive player count is zero");
			}
			else
			{
				currentTargetIndex += direction;
				if (currentTargetIndex >= alivePlayers.Count)
				{
					currentTargetIndex = 0;
				}
				else if (currentTargetIndex < 0)
				{
					currentTargetIndex = alivePlayers.Count - 1;
				}
				currentTargetIndex = Mathf.Clamp(currentTargetIndex, 0, alivePlayers.Count - 1);
				currentTarget = alivePlayers[currentTargetIndex];
			}
			ControlCompanyPlugin.Instance.logger.LogMessage((object)$"Current target index: {currentTargetIndex}");
			ControlCompanyPlugin.Instance.logger.LogMessage((object)("Setting next target to: " + currentTarget?.playerUsername));
		}

		public void SetCurrentTargetToHost()
		{
			currentTargetIndex = 0;
			currentTarget = GetHostPlayer();
			ControlCompanyPlugin.Instance.logger.LogMessage((object)"Setting next target to host");
		}

		private void SetNextSpawnEnemiesPage(int direction)
		{
			List<ControllableEnemy> spawnableEnemies = GetSpawnableEnemies(isGhostIndoors);
			if (spawnableEnemies == null || spawnableEnemies.Count == 0)
			{
				currentSpawnableEnemyList = new List<ControllableEnemy>();
				return;
			}
			if (spawnableEnemies.Count > 12)
			{
				List<IEnumerable<ControllableEnemy>> list = ExtensionMethods.Chunk(spawnableEnemies, 12).ToList();
				currentSpawnEnemiesPage += direction;
				if (currentSpawnEnemiesPage >= list.Count)
				{
					currentSpawnEnemiesPage = 0;
				}
				else if (currentSpawnEnemiesPage < 0)
				{
					currentSpawnEnemiesPage = list.Count - 1;
				}
				currentSpawnEnemiesPage = Mathf.Clamp(currentSpawnEnemiesPage, 0, list.Count - 1);
			}
			else
			{
				currentSpawnEnemiesPage = 0;
			}
			currentSpawnableEnemyList = ExtensionMethods.Chunk(GetSpawnableEnemies(isGhostIndoors), 12).ToList()[currentSpawnEnemiesPage].ToList();
		}

		public List<SpawnableEnemyWithRarity> GetDaytimeEnemies()
		{
			return new List<SpawnableEnemyWithRarity>(GetCurrentLevel().DaytimeEnemies);
		}

		public void StartOfRoundInitialization()
		{
			initialMicPushToTalkSetting = IngamePlayerSettings.Instance.settings.pushToTalk;
			allIndoorEnemies = GetAllIndoorEnemiesAcrossAllMapsList();
			allOutdoorEnemies = GetAllOutdoorEnemiesAcrossAllMapsList();
			indoorEnemiesOfLevel = new List<ControllableEnemy>(GetCurrentLevel().Enemies.Select((SpawnableEnemyWithRarity enemy) => ControllableEnemy.FromSpawnableEnemy(enemy)));
			outdoorEnemiesOfLevel = new List<ControllableEnemy>(from enemy in GetCurrentLevel().OutsideEnemies.Concat(GetCurrentLevel().DaytimeEnemies)
				select ControllableEnemy.FromSpawnableEnemy(enemy));
			ControllableEnemy maskedEnemy = GetMaskedEnemy();
			indoorEnemiesOfLevel.Add(maskedEnemy);
			outdoorEnemiesOfLevel.Add(maskedEnemy);
			allIndoorEnemies.Add(maskedEnemy);
			allOutdoorEnemies.Add(maskedEnemy);
			ControllableEnemy companyMonsterEnemy = GetCompanyMonsterEnemy();
			if (companyMonsterEnemy != null)
			{
				indoorEnemiesOfLevel.Add(companyMonsterEnemy);
				outdoorEnemiesOfLevel.Add(companyMonsterEnemy);
				allIndoorEnemies.Add(companyMonsterEnemy);
				allOutdoorEnemies.Add(companyMonsterEnemy);
			}
			ControllableEnemy secretEnemy = GetSecretEnemy();
			if (secretEnemy != null)
			{
				indoorEnemiesOfLevel.Insert(0, secretEnemy);
				allIndoorEnemies.Insert(0, secretEnemy);
			}
			indoorEnemiesOfLevel = indoorEnemiesOfLevel.DedupeBy((ControllableEnemy enemy) => enemy.EnemyName).ToList();
			outdoorEnemiesOfLevel = outdoorEnemiesOfLevel.DedupeBy((ControllableEnemy enemy) => enemy.EnemyName).ToList();
			allIndoorEnemies = allIndoorEnemies.DedupeBy((ControllableEnemy enemy) => enemy.EnemyName).ToList();
			allOutdoorEnemies = allOutdoorEnemies.DedupeBy((ControllableEnemy enemy) => enemy.EnemyName).ToList();
			gameStartedTime = 0f;
			SetCurrentTargetToHost();
			ResetToDefault();
			inRoundEndPhase = false;
			ControlCompanyPlugin.Instance.logger.LogMessage((object)"Start of round initialization completed.");
		}

		public void EndOfRoundCleanUp()
		{
			ResetToDefault();
			inRoundEndPhase = true;
			ControlCompanyPlugin.Instance.logger.LogMessage((object)"End of round clean up completed.");
		}

		private void ResetToDefault()
		{
			StartOfRound.Instance.audioListener = GetHostPlayer().activeAudioListener;
			GetHostPlayer().isTypingChat = false;
			currentMode = Mode.HOST;
			if ((Object)(object)ghost != (Object)null)
			{
				Object.Destroy((Object)(object)ghost);
				ghost = null;
			}
			if ((Object)(object)currentControlledEnemy != (Object)null)
			{
				currentControlledEnemy.DestroyAndCleanUp();
			}
			currentSpawnableEnemyList = new List<ControllableEnemy>();
			currentSpawnEnemiesPage = 0;
			EnableHostPlayer(enable: true);
			ControlCompanyPlugin.Instance.logger.LogMessage((object)"Reset to default.");
		}

		public bool IsListeningFromHost()
		{
			return ((ButtonControl)InputKeys.HOST_LISTEN_KEY).isPressed;
		}

		public PlayerControllerB GetHostPlayer()
		{
			return RoundManager.Instance.playersManager.allPlayerObjects[0].GetComponentInChildren<PlayerControllerB>();
		}

		public List<PlayerControllerB> GetDeadPlayers()
		{
			return (from player in GetAllPlayers()
				where player.isPlayerDead
				select player).ToList();
		}

		public List<PlayerControllerB> GetAlivePlayers()
		{
			return (from player in GetAllPlayers()
				where !player.isPlayerDead
				select player).ToList();
		}

		public List<PlayerControllerB> GetAllPlayers()
		{
			List<PlayerControllerB> list = new List<PlayerControllerB>();
			GameObject[] allPlayerObjects = RoundManager.Instance.playersManager.allPlayerObjects;
			for (int i = 0; i < allPlayerObjects.Length; i++)
			{
				PlayerControllerB componentInChildren = allPlayerObjects[i].GetComponentInChildren<PlayerControllerB>();
				if ((Object)(object)componentInChildren != (Object)null && componentInChildren.isPlayerControlled)
				{
					list.Add(componentInChildren);
				}
			}
			return list;
		}

		public bool DoesCurrentLevelExist()
		{
			return (Object)(object)GetCurrentLevel() != (Object)null;
		}

		public bool IsGameStarted()
		{
			return (Object)(object)RoundManager.Instance != (Object)null && (Object)(object)RoundManager.Instance.currentLevel != (Object)null && (Object)(object)GameNetworkManager.Instance != (Object)null && GameNetworkManager.Instance.gameHasStarted && (Object)(object)StartOfRound.Instance != (Object)null && !StartOfRound.Instance.inShipPhase;
		}

		public SelectableLevel GetCurrentLevel()
		{
			return RoundManager.Instance.currentLevel;
		}

		public StartOfRound GetPlayersManager()
		{
			return RoundManager.Instance.playersManager;
		}

		private bool IsHost()
		{
			return ((NetworkBehaviour)RoundManager.Instance).IsHost;
		}

		public List<Item> GetSpawnableScraps()
		{
			return StartOfRound.Instance.allItemsList.itemsList;
		}

		public List<ControllableEnemy> GetPagedSpawnableEnemies()
		{
			return currentSpawnableEnemyList;
		}

		public List<ControllableEnemy> GetSpawnableEnemies(bool isIndoor)
		{
			List<ControllableEnemy> list = ((!isIndoor) ? GetSpawnableOutdoorEnemies() : GetSpawnableIndoorEnemies());
			if (list == null || list.Count == 0)
			{
				list = new List<ControllableEnemy>();
			}
			return list;
		}

		public List<ControllableEnemy> GetSpawnableIndoorEnemies()
		{
			return allowAllEnemies ? GetIndoorEnemyList() : GetAllowListedIndoorEnemies();
		}

		public List<ControllableEnemy> GetAllowListedIndoorEnemies()
		{
			return (from enemy in GetIndoorEnemyList()
				where enemy.Allowlisted
				select enemy).ToList();
		}

		public List<ControllableEnemy> GetIndoorEnemyList()
		{
			return allowAllEnemies ? allIndoorEnemies : indoorEnemiesOfLevel;
		}

		public List<ControllableEnemy> GetAllIndoorEnemiesAcrossAllMapsList()
		{
			HashSet<string> hashSet = new HashSet<string>();
			List<ControllableEnemy> list = new List<ControllableEnemy>();
			SelectableLevel[] levels = StartOfRound.Instance.levels;
			foreach (SelectableLevel val in levels)
			{
				if (!((Object)(object)val != (Object)null))
				{
					continue;
				}
				foreach (SpawnableEnemyWithRarity enemy in val.Enemies)
				{
					if ((Object)(object)enemy.enemyType != (Object)null && !hashSet.Contains(enemy.enemyType.enemyName))
					{
						hashSet.Add(enemy.enemyType.enemyName);
						list.Add(ControllableEnemy.FromSpawnableEnemy(enemy));
					}
				}
			}
			return list;
		}

		public List<ControllableEnemy> GetSpawnableOutdoorEnemies()
		{
			return allowAllEnemies ? GetOutdoorEnemyList() : GetAllowListedOutdoorEnemies();
		}

		public List<ControllableEnemy> GetAllowListedOutdoorEnemies()
		{
			return (from enemy in GetOutdoorEnemyList()
				where enemy.Allowlisted
				select enemy).ToList();
		}

		public List<ControllableEnemy> GetOutdoorEnemyList()
		{
			return allowAllEnemies ? allOutdoorEnemies : outdoorEnemiesOfLevel;
		}

		public List<ControllableEnemy> GetAllOutdoorEnemiesAcrossAllMapsList()
		{
			if (GetCurrentLevel().OutsideEnemies.Count == 0)
			{
				return new List<ControllableEnemy>();
			}
			HashSet<string> hashSet = new HashSet<string>();
			List<ControllableEnemy> list = new List<ControllableEnemy>();
			SelectableLevel[] levels = StartOfRound.Instance.levels;
			foreach (SelectableLevel val in levels)
			{
				if (!((Object)(object)val != (Object)null))
				{
					continue;
				}
				IEnumerable<SpawnableEnemyWithRarity> enumerable = val.OutsideEnemies.Concat(val.DaytimeEnemies);
				foreach (SpawnableEnemyWithRarity item in enumerable)
				{
					if ((Object)(object)item.enemyType != (Object)null && !hashSet.Contains(item.enemyType.enemyName))
					{
						hashSet.Add(item.enemyType.enemyName);
						list.Add(ControllableEnemy.FromSpawnableEnemy(item));
					}
				}
			}
			return list;
		}

		public ControllableEnemy GetMaskedEnemy()
		{
			SelectableLevel[] levels = StartOfRound.Instance.levels;
			foreach (SelectableLevel val in levels)
			{
				foreach (SpawnableEnemyWithRarity enemy in val.Enemies)
				{
					EnemyType enemyType = enemy.enemyType;
					object obj;
					if (enemyType == null)
					{
						obj = null;
					}
					else
					{
						GameObject enemyPrefab = enemyType.enemyPrefab;
						obj = ((enemyPrefab != null) ? enemyPrefab.GetComponent<EnemyAI>() : null);
					}
					EnemyAI val2 = (EnemyAI)obj;
					if ((Object)(object)val2 != (Object)null && ((object)val2).GetType() == typeof(MaskedPlayerEnemy))
					{
						return ControllableEnemy.FromSpawnableEnemy(enemy);
					}
				}
			}
			return null;
		}

		private ControllableEnemy GetSecretEnemy()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			Object[] array = Resources.FindObjectsOfTypeAll(typeof(EnemyAI));
			Object[] array2 = array;
			for (int i = 0; i < array2.Length; i++)
			{
				EnemyAI val = (EnemyAI)array2[i];
				if (((object)val).GetType() == typeof(TestEnemy))
				{
					return ControllableEnemy.FromEnemyAI(val);
				}
			}
			return null;
		}

		private GameObject SpawnScrap(Item scrap, Vector3 position)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: 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)
			GameObject val = Object.Instantiate<GameObject>(scrap.spawnPrefab, position, Quaternion.identity);
			GrabbableObject componentInChildren = val.GetComponentInChildren<GrabbableObject>();
			((Component)componentInChildren).transform.rotation = Quaternion.Euler(componentInChildren.itemProperties.restingRotation);
			val.GetComponentInChildren<NetworkObject>().Spawn(true);
			return val;
		}

		private EnemyController SpawnControllableEnemy(ControllableEnemy controllableEnemy, Vector3 position, Quaternion rotation)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: 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_001e: 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_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Expected O, but got Unknown
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = (controllableEnemy.OverrideEnemySpawnLocation ? controllableEnemy.EnemySpawnLocationOverride : (position + new Vector3(0f, 0.5f, 0f)));
			GameObject val2 = (controllableEnemy.OverrideEnemyPrefab ? controllableEnemy.EnemyGameObject : Object.Instantiate<GameObject>(controllableEnemy.EnemyPrefab, val, Quaternion.identity));
			if (!controllableEnemy.OverrideEnemyPrefab)
			{
				val2.GetComponentInChildren<NetworkObject>().Spawn(true);
			}
			GameObject val3 = new GameObject("enemy_controller");
			val3.transform.position = val;
			val3.transform.rotation = rotation;
			if (controllableEnemy.CreateAndAttachEnemyControllerFunc == null)
			{
				throw new Exception("Controllable enemy does not have a function defined to create and attach an enemy controller!");
			}
			EnemyController enemyController = controllableEnemy.CreateAndAttachEnemyControllerFunc(val2, val3);
			enemyController.InitializeEnemyController(GetHostPlayer().playerActions, val2);
			enemyController.EnableLight(isGhostIndoors);
			ChangeAudioListener(enemyController.AudioListener);
			return enemyController;
		}

		private GameObject GetTurretPrefab()
		{
			SelectableLevel[] levels = StartOfRound.Instance.levels;
			foreach (SelectableLevel val in levels)
			{
				SpawnableMapObject[] spawnableMapObjects = val.spawnableMapObjects;
				foreach (SpawnableMapObject val2 in spawnableMapObjects)
				{
					object obj;
					if (val2 == null)
					{
						obj = null;
					}
					else
					{
						GameObject prefabToSpawn = val2.prefabToSpawn;
						obj = ((prefabToSpawn != null) ? prefabToSpawn.GetComponentInChildren<Turret>() : null);
					}
					if ((Object)obj != (Object)null)
					{
						return val2.prefabToSpawn;
					}
				}
			}
			return null;
		}

		private EnemyController SpawnControllableTurret(Vector3 position, Quaternion rotation)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			//IL_0057: 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_007d: Unknown result type (might be due to invalid IL or missing references)
			GameObject turretPrefab = GetTurretPrefab();
			if ((Object)(object)turretPrefab == (Object)null)
			{
				ControlCompanyPlugin.Instance.logger.LogDebug((object)"Cannot find turret prefab in current level");
				return null;
			}
			GameObject val = Object.Instantiate<GameObject>(turretPrefab, position, rotation);
			val.GetComponentInChildren<NetworkObject>().Spawn(true);
			GameObject val2 = new GameObject("enemy_controller");
			val2.transform.position = position + new Vector3(0f, 0.5f, 0f);
			val2.transform.rotation = rotation;
			TurretEnemyController turretEnemyController = val2.AddComponent<TurretEnemyController>();
			turretEnemyController.InitializeEnemyController(GetHostPlayer().playerActions, val);
			turretEnemyController.EnableLight(enable: true);
			return turretEnemyController;
		}

		private ControllableEnemy GetCompanyMonsterEnemy()
		{
			//IL_0078: 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)
			DepositItemsDesk val = Object.FindObjectOfType<DepositItemsDesk>();
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			GameObject val2 = GameObject.Find("BellDinger");
			return new ControllableEnemy
			{
				EnemyName = "Company Monster",
				OverrideEnemyPrefab = true,
				EnemyGameObject = ((Component)val).gameObject,
				Allowlisted = true,
				OverrideEnemySpawnLocation = true,
				EnemySpawnLocationOverride = (((Object)(object)val2 != (Object)null) ? val2.transform.position : ((Component)val).transform.position),
				CreateAndAttachEnemyControllerFunc = (GameObject enemyGameObject, GameObject enemyController) => enemyController.AddComponent<CompanyMonsterController>()
			};
		}

		private DissonanceComms GetMic()
		{
			return StartOfRound.Instance.voiceChatModule;
		}

		private void ForceMicPushToTalk()
		{
			IngamePlayerSettings.Instance.settings.pushToTalk = true;
		}

		private void ResetMicPushToTalk()
		{
			IngamePlayerSettings.Instance.settings.pushToTalk = initialMicPushToTalkSetting;
		}
	}
	internal class DoorOpener : MonoBehaviour
	{
		public void DetectAndOpenDoors(float range)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			Collider[] array = Physics.OverlapSphere(((Component)this).transform.position, range);
			for (int i = 0; i < array.Length; i++)
			{
				DoorLock componentInChildren = ((Component)array[i]).GetComponentInChildren<DoorLock>();
				if ((Object)(object)componentInChildren != (Object)null)
				{
					OpenDoor(componentInChildren);
				}
			}
		}

		public void OpenDoor(DoorLock doorLock)
		{
			if ((Object)(object)doorLock != (Object)null && !doorLock.GetFieldValue<bool>("isDoorOpened"))
			{
				doorLock.OpenDoorAsEnemyServerRpc();
				((Component)doorLock).gameObject.GetComponent<AnimatedObjectTrigger>().TriggerAnimationNonPlayer(false, true, false);
			}
		}
	}
	internal class EnemyController : CustomPlayerController
	{
		protected GameObject enemyGameObject;

		protected bool isAIControlled = false;

		protected bool controlEnemyRotation = true;

		protected bool controlEnemyMovement = true;

		protected bool lockEnemyRotationInput = false;

		public bool IsAIControlled => isAIControlled;

		public virtual void InitializeEnemyController(PlayerActions playerActions, GameObject enemyGameObject)
		{
		}

		public virtual bool CanControlEnemy()
		{
			return true;
		}

		public void SetLockEnemyRotation(bool lockEnemyRotationInput)
		{
			this.lockEnemyRotationInput = lockEnemyRotationInput;
		}

		public void UsePrimarySkill()
		{
			CheckInitialized();
			if (!isAIControlled)
			{
				UsePrimarySkillAction();
			}
		}

		protected virtual void UsePrimarySkillAction()
		{
		}

		public void ReleasePrimarySkill()
		{
			CheckInitialized();
			if (!isAIControlled)
			{
				ReleasePrimarySkillAction();
			}
		}

		protected virtual void ReleasePrimarySkillAction()
		{
		}

		public void UseSecondarySkill()
		{
			CheckInitialized();
			if (!isAIControlled)
			{
				UseSecondarySkillAction();
			}
		}

		protected virtual void UseSecondarySkillAction()
		{
		}

		public void ReleaseSecondarySkill()
		{
			CheckInitialized();
			if (!isAIControlled)
			{
				ReleaseSecondarySkillAction();
			}
		}

		protected virtual void ReleaseSecondarySkillAction()
		{
		}

		protected virtual void EnableAIControl(bool enabled)
		{
			CheckInitialized();
			isAIControlled = enabled;
			ControlCompanyPlugin.Instance.logger.LogMessage((object)$"Enable AI control: {enabled}");
			if (IsAIControlled)
			{
				ToggleAIControlTrue();
			}
			else
			{
				ToggleAIControlFalse();
			}
		}

		protected virtual void ToggleAIControlTrue()
		{
		}

		protected virtual void ToggleAIControlFalse()
		{
		}

		public virtual void ToggleAIControl()
		{
			CheckInitialized();
			isAIControlled = !isAIControlled;
			EnableAIControl(isAIControlled);
		}

		public virtual void DestroyAndCleanUp()
		{
			if (ShouldDestroyEnemyGameObjectOnCleanUp())
			{
				Object.Destroy((Object)(object)enemyGameObject);
			}
			Object.Destroy((Object)(object)((Component)this).gameObject);
		}

		protected virtual bool ShouldDestroyEnemyGameObjectOnCleanUp()
		{
			return true;
		}

		public virtual string GetPrimarySkillName()
		{
			return "";
		}

		public virtual string GetSecondarySkillName()
		{
			return "";
		}

		protected void CheckInitialized()
		{
			if (!isInitialized)
			{
				throw new Exception("Not initialized yet.");
			}
		}

		protected virtual void OnControllerColliderHit(ControllerColliderHit hit)
		{
			DoorLock component = hit.gameObject.GetComponent<DoorLock>();
			if ((Object)(object)component != (Object)null)
			{
				doorOpener.OpenDoor(component);
			}
		}
	}
	internal class EnemyAIController : EnemyController
	{
		private EnemyAI enemyAI;

		private NavMeshAgent enemyAIAgent;

		private float originalAgentAngularSpeed;

		private float originalAgentSpeed;

		private Vector3 enemyPositionOffset = Vector3.zero;

		private bool useLerpRotation = false;

		public EnemyAI EnemyAI => enemyAI;

		public override void InitializeEnemyController(PlayerActions playerActions, GameObject enemyGameObject)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: 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_00ac: Unknown result type (might be due to invalid IL or missing references)
			if (!isInitialized)
			{
				List<Collider> list = enemyGameObject.GetComponentsInChildren<Collider>().ToList();
				Initialize(playerActions, CameraMode.THIRD_PERSON, list);
				CharacterController obj = characterController;
				((Collider)obj).excludeLayers = LayerMask.op_Implicit(LayerMask.op_Implicit(((Collider)obj).excludeLayers) & ~LayerMask.op_Implicit(Constants.ITERACTABLE_OBJ_LAYERMASK));
				enemyAI = GetEnemyAIFromEnemyGameObject(enemyGameObject);
				if ((Object)(object)enemyAI == (Object)null)
				{
					throw new Exception("Enemy gameobject does not have EnemyAI script attached.");
				}
				((Component)enemyAI).gameObject.LogLayer();
				enemyGameObject.transform.position = ((Component)this).transform.position;
				enemyGameObject.transform.rotation = ((Component)this).transform.rotation;
				base.enemyGameObject = enemyGameObject;
				enemyAIAgent = enemyGameObject.GetComponentInChildren<NavMeshAgent>();
				if ((Object)(object)enemyAIAgent != (Object)null)
				{
					originalAgentAngularSpeed = enemyAIAgent.angularSpeed;
					originalAgentSpeed = enemyAIAgent.speed;
				}
				ConfigureEnemyAttributes(enemyAI);
				EnableAIControl(enabled: false);
			}
		}

		protected override void LateUpdate()
		{
			//IL_012f: 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_005c: 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_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			if (!isInitialized)
			{
				return;
			}
			base.LateUpdate();
			if (!isAIControlled)
			{
				if (!CanControlEnemy())
				{
					return;
				}
				if (controlEnemyMovement)
				{
					enemyGameObject.transform.position = ((Component)this).transform.position + enemyPositionOffset;
				}
				if (!controlEnemyRotation || lockEnemyRotationInput)
				{
					return;
				}
				Vector3 velocity = characterController.velocity;
				if (((Vector3)(ref velocity)).sqrMagnitude > 0.1f)
				{
					if (useLerpRotation)
					{
						enemyGameObject.transform.rotation = Quaternion.Lerp(enemyGameObject.transform.rotation, ((Component)this).transform.rotation, 8f * Time.deltaTime);
					}
					else
					{
						enemyGameObject.transform.rotation = ((Component)this).transform.rotation;
					}
				}
			}
			else
			{
				((Component)this).transform.position = enemyGameObject.transform.position;
			}
		}

		protected EnemyAI GetEnemyAIFromEnemyGameObject(GameObject enemyObj)
		{
			return enemyObj.GetComponentInChildren<EnemyAI>();
		}

		private void ConfigureEnemyAttributes(EnemyAI enemyAI)
		{
			//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)
			EnemyAttributes enemyAttributes = enemyAI.GetEnemyAttributes();
			base.WalkSpeed = enemyAttributes.WalkSpeed;
			base.RunSpeed = enemyAttributes.RunSpeed;
			SetCamDistance(enemyAttributes.CamDistance);
			SetCamHeight(enemyAttributes.CamHeight);
			controlEnemyRotation = enemyAttributes.PlayerControlsRotation;
			controlEnemyMovement = true;
			enemyPositionOffset = enemyAttributes.EnemyPositionOffset;
			useLerpRotation = enemyAttributes.UseLerpRotation;
		}

		protected virtual void ConfigureEnemyHandicap(EnemyAI enemyAI)
		{
		}

		public override bool CanControlEnemy()
		{
			return !enemyAI.isEnemyDead;
		}

		protected override void Move()
		{
			if (!enemyAI.isEnemyDead)
			{
				base.Move();
			}
		}

		public void SwitchAIState(int stateIndex)
		{
			CheckInitialized();
			if (!isAIControlled)
			{
				enemyAI.SwitchToBehaviourState(stateIndex);
			}
		}

		protected override void ToggleAIControlTrue()
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)enemyAIAgent != (Object)null)
			{
				enemyAIAgent.angularSpeed = originalAgentAngularSpeed;
				enemyAIAgent.speed = originalAgentSpeed;
				enemyAIAgent.isStopped = false;
				enemyAIAgent.Warp(enemyGameObject.transform.position);
				enemyAIAgent.updatePosition = true;
			}
		}

		protected override void ToggleAIControlFalse()
		{
			if ((Object)(object)enemyAI != (Object)null)
			{
				try
				{
					enemyAI.ChangeOwnershipOfEnemy(ControlCenter.Instance.GetHostPlayer().actualClientId);
				}
				catch (Exception ex)
				{
					ControlCompanyPlugin.Instance.logger.LogDebug((object)("Cannot give host control: " + ex.Message));
				}
			}
			if ((Object)(object)enemyAIAgent != (Object)null)
			{
				enemyAIAgent.angularSpeed = 0f;
				enemyAIAgent.speed = 0f;
				enemyAIAgent.isStopped = true;
				enemyAIAgent.updatePosition = false;
			}
			((Component)this).transform.SetParent((Transform)null);
		}

		protected override bool ShouldDestroyEnemyGameObjectOnCleanUp()
		{
			return !enemyAI.isEnemyDead;
		}

		public override string GetSecondarySkillName()
		{
			return "Secondary Skill";
		}

		protected override void UseSecondarySkillAction()
		{
			enemyAI.SwitchToBehaviourState(1);
		}

		protected override void EnableAIControl(bool enabled)
		{
			base.EnableAIControl(enabled);
			canMove = !isAIControlled;
		}
	}
	internal class CustomPlayerController : MonoBehaviour
	{
		public enum CameraMode
		{
			THIRD_PERSON,
			FIRST_PERSON
		}

		protected bool isInitialized = false;

		protected bool hasControl = false;

		protected bool canMove = false;

		protected bool canRotate = false;

		protected bool canJump = false;

		protected CameraMode camMode;

		protected CharacterController characterController;

		protected GameObject cameraGameObjectParent;

		protected GameObject cameraGameObject;

		protected Camera camera;

		protected Light light;

		protected PlayerActions playerActions;

		protected DoorOpener doorOpener;

		private AudioListener audioListener;

		private float runSpeed = 9f;

		private float walkSpeed = 7f;

		private float camDistance = -3.5f;

		private float camHeight = 2f;

		private float gravity = -20f;

		private float jumpHeight = 4.5f;

		private float currentYVelocity;

		private List<Collider> collidersToIgnore = new List<Collider>();

		public float RunSpeed
		{
			get
			{
				return runSpeed;
			}
			set
			{
				runSpeed = value;
			}
		}

		public float WalkSpeed
		{
			get
			{
				return walkSpeed;
			}
			set
			{
				walkSpeed = value;
			}
		}

		public float Gravity
		{
			get
			{
				return gravity;
			}
			set
			{
				gravity = value;
			}
		}

		public AudioListener AudioListener
		{
			get
			{
				return audioListener;
			}
			set
			{
				audioListener = value;
			}
		}

		public bool IsInitialized
		{
			get
			{
				return isInitialized;
			}
			set
			{
				isInitialized = value;
			}
		}

		public void Initialize(PlayerActions playerActions, CameraMode camMode, List<Collider> collidersToIgnore = null)
		{
			if (!isInitialized)
			{
				this.playerActions = playerActions;
				this.camMode = camMode;
				if (collidersToIgnore != null)
				{
					this.collidersToIgnore = collidersToIgnore;
				}
				characterController = InitializeCharacterController();
				camera = InitializeCamera();
				light = InitializeLight(((Component)camera).gameObject);
				doorOpener = ((Component)this).gameObject.AddComponent<DoorOpener>();
				EnableControl(enable: true);
				isInitialized = true;
			}
		}

		public void EnableLight(bool enable)
		{
			((Behaviour)light).enabled = enable;
		}

		public void EnableCamera(bool enable)
		{
			((Behaviour)camera).enabled = enable;
		}

		public void ToggleLight()
		{
			((Behaviour)light).enabled = !((Behaviour)light).enabled;
		}

		public void EnableControl(bool enable)
		{
			hasControl = enable;
			canMove = enable;
			canRotate = enable;
			canJump = enable;
		}

		public bool IsMoving()
		{
			//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)
			Vector3 velocity = characterController.velocity;
			return ((Vector3)(ref velocity)).sqrMagnitude > 0f;
		}

		public void SetCamHeight(float camHeight)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			this.camHeight = camHeight;
			cameraGameObjectParent.transform.localPosition = new Vector3(0f, camHeight, 0f);
		}

		public void SetCamDistance(float camDistance)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			this.camDistance = camDistance;
			cameraGameObject.transform.localPosition = new Vector3(0f, 0f, (camMode == CameraMode.THIRD_PERSON) ? camDistance : 0f);
		}

		protected virtual void LateUpdate()
		{
			if (isInitialized && hasControl)
			{
				if (canMove)
				{
					Move();
				}
				if (canRotate)
				{
					Rotate();
				}
				if (((ButtonControl)InputKeys.CONTROLLER_USE_KEY).wasPressedThisFrame)
				{
					doorOpener.DetectAndOpenDoors(3f);
				}
			}
		}

		protected virtual Vector3 MoveInput()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			return Vector2.op_Implicit(IngamePlayerSettings.Instance.playerInput.actions.FindAction("Move", false).ReadValue<Vector2>());
		}

		protected virtual bool IsSprinting()
		{
			return IngamePlayerSettings.Instance.playerInput.actions.FindAction("Sprint", false).ReadValue<float>() > 0f;
		}

		protected virtual void Move()
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			bool flag = IsSprinting();
			Vector3 val = MoveInput();
			Vector3 val2 = ((Component)this).transform.right * val.x;
			Vector3 val3 = ((Component)this).transform.forward * val.y;
			bool isGrounded = characterController.isGrounded;
			if (isGrounded && currentYVelocity < 0f)
			{
				currentYVelocity = 0f;
			}
			if (canJump && isGrounded && ((ButtonControl)InputKeys.CONTROLLER_JUMP_KEY).wasPressedThisFrame)
			{
				currentYVelocity += Mathf.Sqrt(jumpHeight * (0f - gravity));
			}
			currentYVelocity += gravity * Time.deltaTime;
			characterController.Move(((val2 + val3) * (flag ? runSpeed : walkSpeed) + new Vector3(0f, currentYVelocity, 0f)) * Time.deltaTime);
		}

		protected virtual void Rotate()
		{
			//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_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			MovementActions movement = playerActions.Movement;
			Vector2 val = ((MovementActions)(ref movement)).Look.ReadValue<Vector2>() * 0.008f * (float)IngamePlayerSettings.Instance.settings.lookSensitivity;
			if (IngamePlayerSettings.Instance.settings.invertYAxis)
			{
				val.y *= -1f;
			}
			((Component)this).transform.Rotate(new Vector3(0f, val.x, 0f));
			cameraGameObjectParent.transform.Rotate(new Vector3(0f - val.y, 0f, 0f));
		}

		private Light InitializeLight(GameObject lightParent)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("controller_light");
			val.transform.SetParent(lightParent.transform);
			val.transform.localPosition = new Vector3(0f, 0.5f, 0f);
			val.transform.localRotation = Quaternion.identity;
			Light val2 = val.AddComponent<Light>();
			val2.range = 15f;
			val2.intensity = 225f;
			val2.cullingMask = -1;
			return val2;
		}

		private CharacterController InitializeCharacterController()
		{
			//IL_001e: 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_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			CharacterController controller = ((Component)this).gameObject.AddComponent<CharacterController>();
			((Collider)controller).excludeLayers = LayerMask.op_Implicit(LayerMask.op_Implicit(Constants.PLAYER_LOS_LAYERMASK) | LayerMask.op_Implicit(Constants.ITERACTABLE_OBJ_LAYERMASK) | LayerMask.op_Implicit(Constants.ENEMIES_LAYERMASK) | LayerMask.op_Implicit(Constants.PROPS_LAYERMASK) | LayerMask.op_Implicit(Constants.PLAYER_RAGDOLL_LAYERMASK));
			controller.center = new Vector3(0f, 0.55f, 0f);
			controller.height = 0.4f;
			ControlCenter.Instance.GetAllPlayers().ForEach(delegate(PlayerControllerB p)
			{
				if ((Object)(object)p != (Object)null)
				{
					((Component)p).GetComponentsInChildren<Collider>().ToList().ForEach(delegate(Collider c)
					{
						Physics.IgnoreCollision(c, (Collider)(object)controller);
					});
				}
			});
			if (collidersToIgnore.Count() > 0)
			{
				foreach (Collider item in collidersToIgnore)
				{
					Physics.IgnoreCollision(item, (Collider)(object)controller);
				}
			}
			controller.slopeLimit = 60f;
			controller.stepOffset = 0.4f;
			return controller;
		}

		private Camera InitializeCamera()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Expected O, but got Unknown
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("controller_cam_parent");
			val.transform.SetParent(((Component)this).transform);
			val.transform.localRotation = Quaternion.identity;
			val.transform.localPosition = new Vector3(0f, camHeight, 0f);
			GameObject val2 = new GameObject("controller_cam");
			val2.transform.SetParent(val.transform);
			val2.transform.localRotation = Quaternion.identity;
			val2.transform.localPosition = new Vector3(0f, 0f, (camMode == CameraMode.THIRD_PERSON) ? camDistance : 0f);
			Camera val3 = val2.AddComponent<Camera>();
			audioListener = val2.AddComponent<AudioListener>();
			cameraGameObject = val2;
			cameraGameObjectParent = val;
			Camera gameplayCamera = ControlCenter.Instance.GetHostPlayer().gameplayCamera;
			val3.cullingMask = gameplayCamera.cullingMask;
			val3.farClipPlane = gameplayCamera.farClipPlane;
			HDAdditionalCameraData component = ((Component)gameplayCamera).gameObject.GetComponent<HDAdditionalCameraData>();
			CopyHDCameraData(val3, component);
			return val3;
		}

		private void CopyHDCameraData(Camera cam, HDAdditionalCameraData dataToCopy)
		{
			//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)
			if ((Object)(object)dataToCopy != (Object)null)
			{
				HDAdditionalCameraData val = ((Component)cam).gameObject.GetComponent<HDAdditionalCameraData>();
				if ((Object)(object)val == (Object)null)
				{
					val = ((Component)cam).gameObject.AddComponent<HDAdditionalCameraData>();
				}
				if ((Object)(object)val != (Object)null)
				{
					val.customRenderingSettings = true;
					val.renderingPathCustomFrameSettingsOverrideMask.mask = dataToCopy.renderingPathCustomFrameSettingsOverrideMask.mask;
					SetCustomPass(val, dataToCopy);
					SetVolumetricFog(val, dataToCopy);
					SetLOD(val, dataToCopy);
					SetAliasing(val, dataToCopy);
					SetShadowQuality(val, dataToCopy);
				}
			}
		}

		private void SetCustomPass(HDAdditionalCameraData camData, HDAdditionalCameraData dataToCopy)
		{
			((FrameSettings)(ref camData.renderingPathCustomFrameSettings)).SetEnabled((FrameSettingsField)6, ((FrameSettings)(ref dataToCopy.renderingPathCustomFrameSettings)).IsEnabled((FrameSettingsField)6));
		}

		private void SetVolumetricFog(HDAdditionalCameraData camData, HDAdditionalCameraData dataToCopy)
		{
			((FrameSettings)(ref camData.renderingPathCustomFrameSettings)).SetEnabled((FrameSettingsField)28, ((FrameSettings)(ref dataToCopy.renderingPathCustomFrameSettings)).IsEnabled((FrameSettingsField)28));
		}

		private void SetLOD(HDAdditionalCameraData camData, HDAdditionalCameraData dataToCopy)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			camData.renderingPathCustomFrameSettings.lodBiasMode = dataToCopy.renderingPathCustomFrameSettings.lodBiasMode;
			camData.renderingPathCustomFrameSettings.lodBias = dataToCopy.renderingPathCustomFrameSettings.lodBias;
		}

		private void SetAliasing(HDAdditionalCameraData camData, HDAdditionalCameraData dataToCopy)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			camData.antialiasing = dataToCopy.antialiasing;
		}

		private void SetShadowQuality(HDAdditionalCameraData camData, HDAdditionalCameraData dataToCopy)
		{
			((FrameSettings)(ref camData.renderingPathCustomFrameSettings)).SetEnabled((FrameSettingsField)20, ((FrameSettings)(ref dataToCopy.renderingPathCustomFrameSettings)).IsEnabled((FrameSettingsField)20));
		}
	}
}
namespace ControlCompany.Core.UI
{
	public class UIInstruction
	{
		public string InputKey { get; set; }

		public string ActionText { get; set; }
	}
	internal class UIManager : MonoBehaviour
	{
		private const float GUI_LABEL_HEIGHT = 36f;

		private const float GUI_LABEL_WIDTH = 750f;

		private const float GUI_PADDING = 32f;

		private const int GUI_FONT_SIZE = 28;

		private const FontStyle GUI_FONT_WEIGHT = 0;

		public static UIManager Instance;

		private void Awake()
		{
			if ((Object)(object)Instance == (Object)null)
			{
				Instance = this;
			}
		}

		public void RenderNotHostLabel(string toggleUIKey)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			GUIStyle val = new GUIStyle(GUI.skin.label)
			{
				alignment = (TextAnchor)3,
				fontSize = 24,
				fontStyle = (FontStyle)0
			};
			val.normal.textColor = Color.red;
			RenderTextTopLeftCorner("Not hosting. ControlCompany mod is disabled. Press " + toggleUIKey + " to hide.", 0f, val, 1000f);
		}

		public void RenderEnemyControls(string primaryKey, string secondaryKey, string aiControlKey, string exitKey, string listenFromHostKey, EnemyController enemyController, PlayerControllerB hostPlayer)
		{
			string primarySkillName = enemyController.GetPrimarySkillName();
			string secondarySkillName = enemyController.GetSecondarySkillName();
			List<UIInstruction> list = new List<UIInstruction>();
			if (enemyController.IsAIControlled)
			{
				list.Add(new UIInstruction
				{
					InputKey = aiControlKey,
					ActionText = "Take control"
				});
			}
			else
			{
				if (!Utility.IsNullOrWhiteSpace(primarySkillName))
				{
					list.Add(new UIInstruction
					{
						InputKey = primaryKey,
						ActionText = primarySkillName
					});
				}
				if (!Utility.IsNullOrWhiteSpace(secondarySkillName))
				{
					list.Add(new UIInstruction
					{
						InputKey = secondaryKey,
						ActionText = secondarySkillName
					});
				}
				list.Add(new UIInstruction
				{
					InputKey = aiControlKey,
					ActionText = "AI control"
				});
			}
			list.Add(new UIInstruction
			{
				InputKey = exitKey,
				ActionText = "Exit"
			});
			RenderPlayerStatus(hostPlayer, listenFromHostKey);
			float height = 0f;
			height = RenderEnemyStatus(enemyController, height);
			RenderEnemySkills(list, height);
		}

		public void RenderHostControls(string ghostModeKey, string cycleLeftKey, string cycleRightKey, PlayerControllerB currentTarget, bool isExtendedModeEnabled, string creditsKey, string entranceTeleportKey, string toggleUIKey)
		{
			List<UIInstruction> list = new List<UIInstruction>();
			list.Add(new UIInstruction
			{
				InputKey = ghostModeKey,
				ActionText = "Ghost mode"
			});
			list.Add(new UIInstruction
			{
				InputKey = $"{cycleLeftKey}/{cycleRightKey}",
				ActionText = "Change target"
			});
			list.Add(new UIInstruction
			{
				InputKey = toggleUIKey,
				ActionText = "Hide UI"
			});
			if (isExtendedModeEnabled)
			{
				list.Add(new UIInstruction
				{
					InputKey = creditsKey,
					ActionText = "Give credits"
				});
				list.Add(new UIInstruction
				{
					InputKey = entranceTeleportKey,
					ActionText = "Teleport to entrance"
				});
			}
			RenderHostControlList(list, currentTarget);
		}

		public void RenderGhostControls(List<string> enemySpawnKeys, string exitKey, string cycleLeftKey, string cycleRightKey, string listenFromHostKey, bool showEnemyPaging, List<ControllableEnemy> enemies, List<Item> scraps, PlayerControllerB hostPlayer, bool scrapSpawnMode)
		{
			List<UIInstruction> list = new List<UIInstruction>();
			if (!scrapSpawnMode)
			{
				if (enemies != null && enemies.Count > 0)
				{
					if (showEnemyPaging)
					{
						list.Add(new UIInstruction
						{
							InputKey = $"{cycleLeftKey}/{cycleRightKey}",
							ActionText = "Change page"
						});
					}
					for (int i = 0; i < enemies.Count && i < enemySpawnKeys.Count; i++)
					{
						GameObject enemyPrefab = enemies[i].EnemyPrefab;
						list.Add(new UIInstruction
						{
							InputKey = enemySpawnKeys[i],
							ActionText = $"Control {enemies[i].EnemyName}"
						});
					}
				}
			}
			else
			{
				for (int j = 0; j < scraps.Count && j < enemySpawnKeys.Count; j++)
				{
					list.Add(new UIInstruction
					{
						InputKey = enemySpawnKeys[j],
						ActionText = $"Spawn {scraps[j].itemName}"
					});
				}
			}
			list.Add(new UIInstruction
			{
				InputKey = exitKey,
				ActionText = "Exit"
			});
			RenderPlayerStatus(hostPlayer, listenFromHostKey);
			RenderGhostControlList(list);
		}

		private void RenderGhostControlList(List<UIInstruction> ghostControls)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			if (ghostControls.Count <= 0)
			{
				return;
			}
			GUIStyle style = new GUIStyle(GUI.skin.label)
			{
				alignment = (TextAnchor)5,
				fontSize = 28,
				fontStyle = (FontStyle)0
			};
			float num = 0f;
			foreach (UIInstruction ghostControl in ghostControls)
			{
				RenderTextTopRightCorner($"{ghostControl.InputKey}: {ghostControl.ActionText}", num, style);
				num += 36f;
			}
		}

		private float RenderMicStatus(float height, PlayerControllerB hostPlayer)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			//IL_00bb: 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)
			GUIStyle val = new GUIStyle(GUI.skin.label)
			{
				alignment = (TextAnchor)3,
				fontSize = 28,
				fontStyle = (FontStyle)0
			};
			float num = height;
			if (IngamePlayerSettings.Instance.settings.micEnabled && (Object)(object)StartOfRound.Instance.voiceChatModule != (Object)null)
			{
				if (!StartOfRound.Instance.voiceChatModule.IsMuted)
				{
					val.normal.textColor = Color.green;
					RenderTextTopLeftCorner(string.Format("{0} mic enabled", hostPlayer.isPlayerDead ? "Dead" : "Player"), num, val);
				}
				else
				{
					val.normal.textColor = Color.red;
					RenderTextTopLeftCorner(string.Format("{0} mic disabled (push to talk)", hostPlayer.isPlayerDead ? "Dead" : "Player"), num, val);
				}
				num += 36f;
			}
			return num;
		}

		private float RenderPlayerStatus(PlayerControllerB hostPlayer, string listenFromHostKey)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Expected O, but got Unknown
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Expected O, but got Unknown
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			GUIStyle val = new GUIStyle(GUI.skin.label)
			{
				alignment = (TextAnchor)3,
				fontSize = 28,
				fontStyle = (FontStyle)0
			};
			if (hostPlayer.isPlayerDead)
			{
				val.normal.textColor = Color.red;
			}
			else
			{
				val.normal.textColor = Color.green;
			}
			float num = 0f;
			RenderTextTopLeftCorner(string.Format("Player status: {0}", hostPlayer.isPlayerDead ? "Dead" : "Alive"), num, val);
			num += 36f;
			if (!hostPlayer.isPlayerDead)
			{
				GUIStyle val2 = new GUIStyle(GUI.skin.label)
				{
					alignment = (TextAnchor)3,
					fontSize = 28,
					fontStyle = (FontStyle)0
				};
				bool flag = !HostIsNearOtherPlayers(hostPlayer);
				if (flag)
				{
					val2.normal.textColor = Color.green;
				}
				else
				{
					val2.normal.textColor = Color.red;
				}
				RenderTextTopLeftCorner(string.Format("Player proximity: {0}", flag ? "Alone" : "Near others"), num, val2);
				num += 36f;
				GUIStyle val3 = new GUIStyle(GUI.skin.label)
				{
					alignment = (TextAnchor)3,
					fontSize = 28,
					fontStyle = (FontStyle)0
				};
				bool flag2 = ControlCenter.Instance.IsListeningFromHost();
				if (flag2)
				{
					val3.normal.textColor = Color.green;
				}
				else
				{
					val3.normal.textColor = Color.red;
				}
				RenderTextTopLeftCorner(string.Format("Listening from host: {0}", flag2 ? "Yes" : ("No (hold " + listenFromHostKey + ")")), num, val3);
				num += 36f;
			}
			return num + RenderMicStatus(num, hostPlayer);
		}

		private void RenderHostControlList(List<UIInstruction> hostControls, PlayerControllerB currentTarget)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			if (hostControls.Count <= 0)
			{
				return;
			}
			GUIStyle style = new GUIStyle(GUI.skin.label)
			{
				alignment = (TextAnchor)5,
				fontSize = 28,
				fontStyle = (FontStyle)0
			};
			float num = 0f;
			if ((Object)(object)currentTarget != (Object)null)
			{
				RenderTextTopRightCorner($"Spawn target: {currentTarget.playerUsername}", num, style);
				num += 36f;
			}
			foreach (UIInstruction hostControl in hostControls)
			{
				RenderTextTopRightCorner($"{hostControl.InputKey}: {hostControl.ActionText}", num, style);
				num += 36f;
			}
		}

		private float RenderEnemyStatus(EnemyController enemyController, float height)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			float num = height;
			if (enemyController.IsAIControlled)
			{
				GUIStyle val = new GUIStyle(GUI.skin.label)
				{
					alignment = (TextAnchor)5,
					fontSize = 28,
					fontStyle = (FontStyle)0
				};
				val.normal.textColor = Color.red;
				RenderTextTopRightCorner("AI controlled", num, val);
				num += 36f;
			}
			return num;
		}

		private float RenderEnemySkills(List<UIInstruction> playerEnemyControls, float height)
		{
			//IL_001e: 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_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			float num = height;
			if (playerEnemyControls.Count > 0)
			{
				GUIStyle style = new GUIStyle(GUI.skin.label)
				{
					alignment = (TextAnchor)5,
					fontSize = 28,
					fontStyle = (FontStyle)0
				};
				foreach (UIInstruction playerEnemyControl in playerEnemyControls)
				{
					RenderTextTopRightCorner($"{playerEnemyControl.InputKey}: {playerEnemyControl.ActionText}", num, style);
					num += 36f;
				}
			}
			return num;
		}

		private void RenderTextMiddle(string text, float yPos, GUIStyle style)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			GUI.Label(new Rect((float)Screen.width / 2f - 375f, yPos + 32f, 750f, 36f), text, style);
		}

		private void RenderTextTopRightCorner(string text, float yPos, GUIStyle style)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			GUI.Label(new Rect((float)Screen.width - 750f - 32f, yPos + 32f, 750f, 36f), text, style);
		}

		private void RenderTextTopLeftCorner(string text, float yPos, GUIStyle style, float widthOverride = -1f)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			GUI.Label(new Rect(32f, yPos + 32f, (widthOverride > 0f) ? widthOverride : 750f, 36f), text, style);
		}

		private bool HostIsNearOtherPlayers(PlayerControllerB hostPlayer)
		{
			return (bool)hostPlayer.Call("NearOtherPlayers", hostPlayer, 17f);
		}
	}
}
namespace ControlCompany.Core.Input
{
	public static class InputKeys
	{
		public static KeyControl EXIT_KEY = Keyboard.current.escapeKey;

		public static KeyControl EXTENDED_MODE_KEY = Keyboard.current.digit0Key;

		public static KeyControl TOGGLE_UI_KEY = Keyboard.current.uKey;

		public static KeyControl CYCLE_KEY_LEFT = Keyboard.current.oKey;

		public static KeyControl CYCLE_KEY_RIGHT = Keyboard.current.pKey;

		public static KeyControl HOST_LISTEN_KEY = Keyboard.current.leftAltKey;

		public static KeyControl HOST_GHOST_MODE_KEY = Keyboard.current.f1Key;

		public static KeyControl HOST_GIVE_CREDITS_KEY = Keyboard.current.digit8Key;

		public static KeyControl HOST_TELEPORT_TO_ENTRANCE_KEY = Keyboard.current.digit9Key;

		public static KeyControl GHOST_SPAWN_ENEMY_1 = Keyboard.current.f1Key;

		public static KeyControl GHOST_SPAWN_ENEMY_2 = Keyboard.current.f2Key;

		public static KeyControl GHOST_SPAWN_ENEMY_3 = Keyboard.current.f3Key;

		public static KeyControl GHOST_SPAWN_ENEMY_4 = Keyboard.current.f4Key;

		public static KeyControl GHOST_SPAWN_ENEMY_5 = Keyboard.current.f5Key;

		public static KeyControl GHOST_SPAWN_ENEMY_6 = Keyboard.current.f6Key;

		public static KeyControl GHOST_SPAWN_ENEMY_7 = Keyboard.current.f7Key;

		public static KeyControl GHOST_SPAWN_ENEMY_8 = Keyboard.current.f8Key;

		public static KeyControl GHOST_SPAWN_ENEMY_9 = Keyboard.current.f9Key;

		public static KeyControl GHOST_SPAWN_ENEMY_10 = Keyboard.current.f10Key;

		public static KeyControl GHOST_SPAWN_ENEMY_11 = Keyboard.current.f11Key;

		public static KeyControl GHOST_SPAWN_ENEMY_12 = Keyboard.current.f12Key;

		public static List<KeyControl> GHOST_SPAWN_ENEMY_KEYS = new List<KeyControl>();

		public static KeyControl ENEMY_TOGGLE_AI_KEY = Keyboard.current.f1Key;

		public static ButtonControl ENEMY_PRIMARY_SKILL_BUTTON = Mouse.current.leftButton;

		public static ButtonControl ENEMY_SECONDARY_SKILL_BUTTON = Mouse.current.rightButton;

		public static KeyControl LOCK_ENEMY_ROTATION_KEY = Keyboard.current.rightAltKey;

		public static KeyControl ENEMY_TOGGLE_LIGHT_KEY = Keyboard.current.lKey;

		public static KeyControl CONTROLLER_USE_KEY = Keyboard.current.eKey;

		public static KeyControl CONTROLLER_JUMP_KEY = Keyboard.current.spaceKey;
	}
}
namespace ControlCompany.Core.Extentions
{
	public static class ExtensionMethods
	{
		public static T GetFieldValue<T>(this object obj, string name)
		{
			return (T)(obj.GetType().GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(obj));
		}

		public static void SetFieldValue<T>(this object obj, string method, T value)
		{
			obj.GetType().GetField(method, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.SetField | BindingFlags.SetProperty)?.SetValue(obj, value);
		}

		public static object Call(this object o, string methodName, params object[] args)
		{
			MethodInfo method = o.GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.NonPublic);
			if (method != null)
			{
				return method.Invoke(o, args);
			}
			return null;
		}

		public static TValue GetValueOrDefault<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, TValue defaultValue)
		{
			if (dictionary.TryGetValue(key, out var value))
			{
				return value;
			}
			return defaultValue;
		}

		public static IEnumerable<IEnumerable<T>> Chunk<T>(this IEnumerable<T> source, int chunksize)
		{
			while (source.Any())
			{
				yield return source.Take(chunksize);
				source = source.Skip(chunksize);
			}
		}

		public static IEnumerable<T> DedupeBy<T>(this IEnumerable<T> source, Func<T, string> dedupeFunc)
		{
			return from t in source
				group t by dedupeFunc(t) into t
				select t.First();
		}

		public static void LogLayer(this GameObject gameObject)
		{
			ControlCompanyPlugin.Instance.logger.LogMessage((object)$"Enemy layer ({LayerMask.LayerToName(gameObject.layer)}): {gameObject.layer}");
		}

		public static void LogGameObjectName(this GameObject gameObject)
		{
			ControlCompanyPlugin.Instance.logger.LogMessage((object)string.Format("GameObject name: {0}, parent: {1}", ((Object)gameObject).name, ((Object)(object)gameObject.transform.parent != (Object)null) ? ((Object)gameObject.transform.parent).name : "null"));
		}

		public static void LogAllComponents(this GameObject gameObject)
		{
			Component[] components = gameObject.GetComponents<Component>();
			foreach (Component val in components)
			{
				_ = $"GameObject ({((Object)gameObject).name}) component: {((Object)val).name}";
			}
		}

		public static void LogPosition(this GameObject gameObject)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			ControlCompanyPlugin.Instance.logger.LogMessage((object)$"GameObject ({((Object)gameObject).name}) position: {gameObject.transform.position}, local position: {gameObject.transform.localPosition}");
		}

		public static string RemoveChar(this string input, char charToRemove)
		{
			int num = input.IndexOf(charToRemove);
			if (num < 0)
			{
				return input;
			}
			return input.Remove(num, 1).RemoveChar(charToRemove);
		}

		public static bool IsObjectWithinAngle(this Transform transform, Transform other, Vector3 direction, float angleBounds)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = other.position - transform.position;
			float num = Vector3.Angle(val, direction);
			return Mathf.Abs(num) <= angleBounds;
		}
	}
}
namespace ControlCompany.Core.Enemy
{
	internal class ClaySurgeonEnemyController : EnemyAIController
	{
		private ClaySurgeonAI surgeonAI;

		public override void InitializeEnemyController(PlayerActions playerActions, GameObject enemyGameObject)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected O, but got Unknown
			surgeonAI = (ClaySurgeonAI)GetEnemyAIFromEnemyGameObject(enemyGameObject);
			surgeonAI.SyncMasterClaySurgeonClientRpc();
			base.InitializeEnemyController(playerActions, enemyGameObject);
		}

		protected override void Move()
		{
			if (IsJumpingAndSnipping())
			{
				base.Move();
			}
		}

		private bool IsJumpingAndSnipping()
		{
			return surgeonAI.isJumping && ((EnemyAI)surgeonAI).agent.speed > 0f;
		}

		protected override void LateUpdate()
		{
			//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)
			if (!isInitialized)
			{
				return;
			}
			base.LateUpdate();
			if (!isAIControlled && hasControl)
			{
				controlEnemyRotation = IsJumpingAndSnipping();
				Vector3 val = MoveInput();
				if (((Vector3)(ref val)).sqrMagnitude <= 0.1f)
				{
					surgeonAI.SetFieldValue("beatTimer", surgeonAI.currentInterval / 4f);
				}
			}
		}

		protected override void UseSecondarySkillAction()
		{
		}

		protected override void ReleaseSecondarySkillAction()
		{
		}

		protected override void UsePrimarySkillAction()
		{
		}

		public override string GetPrimarySkillName()
		{
			return "";
		}

		public override string GetSecondarySkillName()
		{
			return "";
		}
	}
	internal class FlowerSnakeEnemyController : EnemyAIController
	{
		private FlowerSnakeEnemy flowerSnakeAI;

		private bool canLeap = true;

		private float leapCooldownTime = 1f;

		private float leapCooldownTimer;

		public override void InitializeEnemyController(PlayerActions playerActions, GameObject enemyGameObject)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected O, but got Unknown
			flowerSnakeAI = (FlowerSnakeEnemy)GetEnemyAIFromEnemyGameObject(enemyGameObject);
			base.InitializeEnemyController(playerActions, enemyGameObject);
		}

		protected override void LateUpdate()
		{
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			if (!isInitialized)
			{
				return;
			}
			base.LateUpdate();
			if (isAIControlled)
			{
				return;
			}
			bool flag = IsClingingToPlayer();
			bool fieldValue = flowerSnakeAI.GetFieldValue<bool>("leaping");
			if (flag || fieldValue)
			{
				controlEnemyMovement = false;
				controlEnemyRotation = false;
				((Component)this).transform.position = enemyGameObject.transform.position;
			}
			else
			{
				controlEnemyMovement = true;
				controlEnemyRotation = true;
			}
			if (!flag && !fieldValue && !canLeap)
			{
				leapCooldownTimer += Time.deltaTime;
				if (leapCooldownTimer >= leapCooldownTime)
				{
					leapCooldownTimer = 0f;
					canLeap = true;
				}
			}
		}

		protected override void UsePrimarySkillAction()
		{
			if (IsClingingToPlayer())
			{
				if ((Object)(object)flowerSnakeAI.clingingToPlayer != (Object)null)
				{
					flowerSnakeAI.StopClingingServerRpc((int)GameNetworkManager.Instance.localPlayerController.playerClientId);
				}
			}
			else if (canLeap && !flowerSnakeAI.GetFieldValue<bool>("leaping"))
			{
				LeapForward();
			}
		}

		public override string GetPrimarySkillName()
		{
			return IsClingingToPlayer() ? "Stop clinging" : "Leap";
		}

		protected override void UseSecondarySkillAction()
		{
			if (IsClingingToPlayer() && !flowerSnakeAI.activatedFlight)
			{
			}
		}

		public override string GetSecondarySkillName()
		{
			return "";
		}

		private bool IsClingingToPlayer()
		{
			return (Object)(object)flowerSnakeAI.clingingToPlayer != (Object)null;
		}

		private void LeapForward()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: 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_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = ((Component)this).transform.forward * 2f;
			val += Random.insideUnitSphere * Random.Range(0.05f, 0.15f);
			val.y = Mathf.Clamp(val.y, -16f, 16f);
			val = Vector3.Normalize(val * 1000f);
			flowerSnakeAI.StartLeapOnLocalClient(val);
			flowerSnakeAI.StartLeapClientRpc(val);
		}
	}
	internal class RadMechEnemyController : EnemyAIController
	{
		private RadMechAI radMechAI;

		private float originalRunSpeed = 0f;

		private float originalWalkSpeed = 0f;

		private float scanTargetRange = 200f;

		private float fireRate;

		private float shootTimer = 0f;

		private float locateNewTargetTime = 2f;

		private float locateNewTargetTimer = 0f;

		private bool isFiring = false;

		private int visibleThreatsMask;

		public override void InitializeEnemyController(PlayerActions playerActions, GameObject enemyGameObject)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected O, but got Unknown
			radMechAI = (RadMechAI)GetEnemyAIFromEnemyGameObject(enemyGameObject);
			base.InitializeEnemyController(playerActions, enemyGameObject);
			originalRunSpeed = base.RunSpeed;
			originalWalkSpeed = base.WalkSpeed;
			visibleThreatsMask = radMechAI.GetFieldValue<int>("visibleThreatsMask");
			fireRate = radMechAI.fireRate;
			AdjustAudio();
		}

		protected override void LateUpdate()
		{
			//IL_0055: 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)
			if (!isInitialized)
			{
				return;
			}
			base.LateUpdate();
			if (isAIControlled || !hasControl)
			{
				return;
			}
			radMechAI.SetFieldValue("shootTimer", 0f);
			Vector3 val = MoveInput();
			if (((Vector3)(ref val)).sqrMagnitude <= 0.1f)
			{
				radMechAI.SetFieldValue("walkStepTimer", 0.1f);
				radMechAI.SetFieldValue("takingStep", value: false);
			}
			else
			{
				if (radMechAI.aimingGun && !isFiring)
				{
					radMechAI.SetAimingGun(false);
				}
				bool fieldValue = radMechAI.GetFieldValue<bool>("takingStep");
				float fieldValue2 = radMechAI.GetFieldValue<float>("walkStepTimer");
				radMechAI.SetFieldValue("walkStepTimer", Mathf.Min(fieldValue2, 0.7f));
				if (!fieldValue)
				{
					base.RunSpeed = 0f;
					base.WalkSpeed = 0f;
					if (IsSprinting())
					{
						radMechAI.SetFieldValue("walkStepTimer", Mathf.Min(fieldValue2, 0.2f));
					}
				}
				else
				{
					base.RunSpeed = originalRunSpeed;
					base.WalkSpeed = originalWalkSpeed;
				}
			}
			if (isFiring)
			{
				shootTimer += Time.deltaTime;
				locateNewTargetTimer += Time.deltaTime;
				if (locateNewTargetTimer >= locateNewTargetTime)
				{
					locateNewTargetTimer = 0f;
					ScanAndSetTarget();
				}
				if (!radMechAI.aimingGun)
				{
					radMechAI.SetAimingGun(true);
				}
				if (shootTimer >= fireRate)
				{
					shootTimer = 0f;
					radMechAI.StartShootGun();
				}
			}
		}

		protected override void UsePrimarySkillAction()
		{
			if ((Object)(object)radMechAI.focusedThreatTransform == (Object)null)
			{
				ScanAndSetTarget();
			}
			if ((Object)(object)radMechAI.focusedThreatTransform != (Object)null)
			{
				((EnemyAI)radMechAI).SwitchToBehaviourState(1);
				isFiring = true;
			}
		}

		protected override void ReleasePrimarySkillAction()
		{
			isFiring = false;
			shootTimer = 0f;
			locateNewTargetTimer = 0f;
			radMechAI.SetAimingGun(false);
			((EnemyAI)radMechAI).SwitchToBehaviourState(0);
		}

		protected override void UseSecondarySkillAction()
		{
		}

		protected override void ReleaseSecondarySkillAction()
		{
		}

		public override void DestroyAndCleanUp()
		{
			((MonoBehaviour)this).StartCoroutine(DelayedDestroyAndCleanUp());
		}

		private IEnumerator DelayedDestroyAndCleanUp()
		{
			EnableControl(enable: false);
			EnableCamera(enable: false);
			yield return (object)new WaitForSeconds(3f);
			base.DestroyAndCleanUp();
		}

		public override string GetPrimarySkillName()
		{
			return "Fire";
		}

		public override string GetSecondarySkillName()
		{
			return "";
		}

		private void AdjustAudio()
		{
			AudioSource creatureSFX = ((EnemyAI)radMechAI).creatureSFX;
			creatureSFX.volume *= 0.25f;
			AudioSource localLRADAudio = radMechAI.LocalLRADAudio;
			localLRADAudio.volume *= 0.25f;
			AudioSource localLRADAudio2 = radMechAI.LocalLRADAudio2;
			localLRADAudio2.volume *= 0.25f;
			AudioSource explosionAudio = radMechAI.explosionAudio;
			explosionAudio.volume *= 0.25f;
			AudioSource blowtorchAudio = radMechAI.blowtorchAudio;
			blowtorchAudio.volume *= 0.25f;
			AudioSource flyingDistantAudio = radMechAI.flyingDistantAudio;
			flyingDistantAudio.volume *= 0.25f;
			AudioSource spotlightOnAudio = radMechAI.spotlightOnAudio;
			spotlightOnAudio.volume *= 0.25f;
			AudioSource chargeForwardAudio = radMechAI.chargeForwardAudio;
			chargeForwardAudio.volume *= 0.25f;
			AudioSource engineSFX = radMechAI.engineSFX;
			engineSFX.volume *= 0.25f;
			AudioSource chargeForwardAudio2 = radMechAI.chargeForwardAudio;
			chargeForwardAudio2.volume *= 0.25f;
			AudioSource chargeForwardAudio3 = radMechAI.chargeForwardAudio;
			chargeForwardAudio3.volume *= 0.25f;
		}

		private void FireGun()
		{
		}

		private void ReloadGun()
		{
		}

		private void ScanAndSetTarget()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unkn