Decompiled source of BrutalCompanyAdditions v2.1.1

BepInEx/plugins/Sculas.BrutalCompanyAdditions.dll

Decompiled 11 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using BrutalCompanyAdditions.Events;
using BrutalCompanyAdditions.Objects;
using BrutalCompanyAdditions.Patches;
using BrutalCompanyPlus;
using BrutalCompanyPlus.BCP;
using GameNetcodeStuff;
using HarmonyLib;
using JetBrains.Annotations;
using Microsoft.CodeAnalysis;
using MonoMod.Utils;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.AI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("Sculas.BrutalCompanyAdditions")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Adds more events to Brutal Company!")]
[assembly: AssemblyFileVersion("2.1.1.0")]
[assembly: AssemblyInformationalVersion("2.1.1")]
[assembly: AssemblyProduct("BrutalCompanyAdditions")]
[assembly: AssemblyTitle("Sculas.BrutalCompanyAdditions")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2.1.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
internal class <Module>
{
	static <Module>()
	{
		NetworkVariableSerializationTypes.InitializeSerializer_UnmanagedINetworkSerializable<CurrentNetEvent>();
		NetworkVariableSerializationTypes.InitializeEqualityChecker_UnmanagedIEquatable<CurrentNetEvent>();
	}
}
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace BrutalCompanyAdditions
{
	public static class EventRegistry
	{
		public static readonly List<IEvent> Events = new List<IEvent>
		{
			new BlingBling(),
			new TheVault(),
			new MovingTurrets()
		};

		private static readonly List<EventEnum> OriginalEvents = Plugin.eventWeightEntries.Where(delegate(KeyValuePair<EventEnum, ConfigEntry<int>> kvp)
		{
			KeyValuePair<EventEnum, ConfigEntry<int>> keyValuePair2 = kvp;
			return keyValuePair2.Value.Value > 0;
		}).Select(delegate(KeyValuePair<EventEnum, ConfigEntry<int>> kvp)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			KeyValuePair<EventEnum, ConfigEntry<int>> keyValuePair = kvp;
			return keyValuePair.Key;
		}).ToList();

		public static readonly Dictionary<string, EventEnum> AllEvents = new Dictionary<string, EventEnum>();

		private static readonly int OriginalEventCount = Plugin.eventWeightEntries.Count;

		public static List<EventEnum> SelectableEvents;

		public static bool IsCustomEvent(EventEnum EventId)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Invalid comparison between Unknown and I4
			return (int)EventId >= OriginalEventCount;
		}

		public static IEvent GetEvent(EventEnum EventId)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected I4, but got Unknown
			return Events[EventId - OriginalEventCount];
		}

		public static IEvent GetEventByType<T>() where T : IEvent
		{
			return Events.Find((IEvent Event) => Event.GetType() == typeof(T));
		}

		private static int GetEventId(IEvent Event)
		{
			return OriginalEventCount + Events.IndexOf(Event);
		}

		public static string GetEventName(EventEnum EventId)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			if (!IsCustomEvent(EventId))
			{
				return ((object)(EventEnum)(ref EventId)).ToString();
			}
			return GetEvent(EventId).Name;
		}

		public static void Initialize()
		{
			List<EventEnum> second = (from kvp in PluginConfig.EventConfig.Where(delegate(KeyValuePair<string, ConfigEntry<bool>> kvp)
				{
					KeyValuePair<string, ConfigEntry<bool>> keyValuePair2 = kvp;
					return keyValuePair2.Value.Value;
				})
				select GetEventId(Events.Find(delegate(IEvent Event)
				{
					string name = Event.Name;
					KeyValuePair<string, ConfigEntry<bool>> keyValuePair = kvp;
					return name == keyValuePair.Key;
				}))).Cast<EventEnum>().ToList();
			List<EventEnum> first = new List<EventEnum>();
			IEnumerable<EventEnum> second2;
			if (!PluginConfig.CustomOnly.Value)
			{
				IEnumerable<EventEnum> originalEvents = OriginalEvents;
				second2 = originalEvents;
			}
			else
			{
				IEnumerable<EventEnum> originalEvents = (IEnumerable<EventEnum>)(object)new EventEnum[0];
				second2 = originalEvents;
			}
			SelectableEvents = first.Concat(second2).Concat(second).ToList();
			Extensions.AddRange<string, EventEnum>(AllEvents, Plugin.eventWeightEntries.ToDictionary(delegate(KeyValuePair<EventEnum, ConfigEntry<int>> Event)
			{
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				EventEnum key = Event.Key;
				return ((object)(EventEnum)(ref key)).ToString();
			}, (KeyValuePair<EventEnum, ConfigEntry<int>> Event) => Event.Key));
			Extensions.AddRange<string, EventEnum>(AllEvents, Events.ToDictionary((IEvent Event) => Event.Name, (IEvent Event) => (EventEnum)GetEventId(Event)));
		}

		public static bool IsActive(this IEvent Event)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Invalid comparison between Unknown and I4
			return (int)Utils.LastEvent == GetEventId(Event);
		}
	}
	[BepInPlugin("Sculas.BrutalCompanyAdditions", "BrutalCompanyAdditions", "2.1.1")]
	[BepInProcess("Lethal Company.exe")]
	public class Plugin : BaseUnityPlugin
	{
		private static bool _loaded;

		public static ManualLogSource Logger;

		public static GameObject BCNetworkManagerPrefab;

		private void Awake()
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			Logger = ((BaseUnityPlugin)this).Logger;
			PluginConfig.Bind(this);
			EventRegistry.Initialize();
			InitializeNetcode();
			InitializeBCNetworkManager();
			Harmony val = new Harmony("Sculas.BrutalCompanyAdditions");
			val.PatchAll(typeof(BCPatches));
			val.PatchAll(typeof(AIPatches));
			val.PatchAll(typeof(TerminalPatches));
			Logger.LogWarning((object)"I'm alive! Time to rule the world >:]");
		}

		private void Start()
		{
			InitializeBCManager();
		}

		private void OnDestroy()
		{
			InitializeBCManager();
		}

		private static void InitializeBCManager()
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			if (!_loaded)
			{
				Logger.LogWarning((object)"Initializing BCManager...");
				Object.DontDestroyOnLoad((Object)new GameObject("Sculas.BrutalCompanyAdditions", new Type[1] { typeof(BCManager) }));
				_loaded = true;
			}
		}

		private static void InitializeBCNetworkManager()
		{
			Logger.LogWarning((object)"Initializing BCNetworkManager...");
			AssetBundle val = AssetBundle.LoadFromStream(Assembly.GetExecutingAssembly().GetManifestResourceStream("BrutalCompanyAdditions.Assets.brutalcompanyadditions"));
			BCNetworkManagerPrefab = val.LoadAsset<GameObject>("Assets/BCNetworkManager.prefab");
			BCNetworkManagerPrefab.AddComponent<BCNetworkManager>();
			val.Unload(false);
		}

		private static void InitializeNetcode()
		{
			Type[] types = Assembly.GetExecutingAssembly().GetTypes();
			foreach (Type type in types)
			{
				MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic);
				MethodInfo[] array = methods;
				foreach (MethodInfo methodInfo in array)
				{
					object[] customAttributes = methodInfo.GetCustomAttributes(typeof(RuntimeInitializeOnLoadMethodAttribute), inherit: false);
					if (!customAttributes.IsEmpty())
					{
						Logger.LogWarning((object)("Initializing RPCs for " + type.Name + "..."));
						methodInfo.Invoke(null, null);
					}
				}
			}
		}
	}
	public static class PluginConfig
	{
		public static ConfigEntry<bool> CustomOnly { get; private set; }

		public static Dictionary<string, ConfigEntry<bool>> EventConfig { get; } = new Dictionary<string, ConfigEntry<bool>>();


		public static ConfigEntry<int> TurretDamage { get; private set; }

		public static ConfigEntry<bool> DebugAI { get; private set; }

		public static ConfigEntry<bool> DebugAILogging { get; private set; }

		public static void Bind(Plugin Plugin)
		{
			CustomOnly = ((BaseUnityPlugin)Plugin).Config.Bind<bool>("General", "CustomOnly", false, "Whether to only use custom events or not.");
			foreach (IEvent @event in EventRegistry.Events)
			{
				EventConfig[@event.Name] = ((BaseUnityPlugin)Plugin).Config.Bind<bool>("Events", @event.Name, true, @event.Description + " (default: enabled)");
				bool value = EventConfig[@event.Name].Value;
				Plugin.Logger.LogInfo((object)("Event " + @event.Name + " is " + (value ? "enabled" : "disabled") + "."));
			}
			TurretDamage = ((BaseUnityPlugin)Plugin).Config.Bind<int>("Difficulty", "TurretDamage", 25, "Amount of damage a turret does to a player during the MovingTurrets event (vanilla: 50)");
			DebugAI = ((BaseUnityPlugin)Plugin).Config.Bind<bool>("Advanced", "DebugAI", false, "Whether to show debug text above custom enemies or not (host only, can cause mild lag).");
			DebugAILogging = ((BaseUnityPlugin)Plugin).Config.Bind<bool>("Advanced", "DebugAILogging", false, "Whether to enable logging for AI (can cause extreme lag).");
		}
	}
	public static class Utils
	{
		private static readonly EventEnum InvalidEvent = (EventEnum)(-1);

		public static EventEnum ForcedEvent = InvalidEvent;

		public static EventEnum LastEvent = (EventEnum)0;

		public static bool IsEventForced => ForcedEvent != InvalidEvent;

		public static void ReplaceScrap(this SelectableLevel Level, string ItemName, int Rarity, int MinValue, int MaxValue)
		{
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Expected O, but got Unknown
			float oldMultiplier = RoundManager.Instance.scrapValueMultiplier;
			RoundManager.Instance.scrapValueMultiplier = 1f;
			List<SpawnableItemWithRarity> oldScrap = new List<SpawnableItemWithRarity>(Level.spawnableScrap);
			Item val = Object.Instantiate<Item>(FindItemByName(ItemName));
			val.minValue = MinValue;
			val.maxValue = MaxValue;
			Level.spawnableScrap.Clear();
			Level.spawnableScrap.Add(new SpawnableItemWithRarity
			{
				rarity = Rarity,
				spawnableItem = val
			});
			BCManager.Instance.ExecuteAfterDelay(delegate
			{
				RoundManager.Instance.scrapValueMultiplier = oldMultiplier;
				Level.spawnableScrap = oldScrap;
			}, 12f);
		}

		private static Item FindItemByName(string ItemName)
		{
			return StartOfRound.Instance.allItemsList.itemsList.First((Item Item) => Item.itemName == ItemName);
		}

		public static bool IsObjectTypeOf<T>(this SpawnableMapObject MapObject, out T Component)
		{
			Component = MapObject.prefabToSpawn.GetComponentInChildren<T>();
			return Component != null;
		}

		public static EventEnum SelectRandomEvent()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: 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_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_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_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			if (ForcedEvent != InvalidEvent)
			{
				LastEvent = ForcedEvent;
				ForcedEvent = InvalidEvent;
				return LastEvent;
			}
			switch (EventRegistry.SelectableEvents.Count)
			{
			case 0:
				LastEvent = (EventEnum)0;
				return (EventEnum)0;
			case 1:
				return LastEvent = EventRegistry.SelectableEvents[0];
			}
			EventEnum val;
			do
			{
				int num = Random.Range(0, EventRegistry.SelectableEvents.Count);
				val = EventRegistry.SelectableEvents[num];
				Plugin.Logger.LogWarning((object)$"Selected event {num} ({val}), last event was {LastEvent}");
			}
			while (val == LastEvent);
			return LastEvent = val;
		}

		public static bool TryFindEventByName(string Name, out EventEnum SelectedEvent)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected I4, but got Unknown
			SelectedEvent = (EventEnum)(int)EventRegistry.AllEvents.TryGetFirst((KeyValuePair<string, EventEnum> EventName) => EventName.Key.StartsWith(Name, StringComparison.InvariantCultureIgnoreCase), out var Found).Value;
			return Found;
		}

		public static void SendEventMessage(IEvent Event)
		{
			string text = Event.Positivity switch
			{
				EventPositivity.Positive => "green", 
				EventPositivity.Neutral => "white", 
				EventPositivity.Negative => "red", 
				EventPositivity.Golden => "orange", 
				_ => "white", 
			};
			HUDManager.Instance.AddTextToChatOnServer("<color=yellow>EVENT<color=white>:</color></color>\n<color=" + text + ">" + Event.Name + "</color>\n<color=white><size=70%>" + Event.Description + "</size></color>", -1);
		}

		public static bool IsEmpty<T>(this IEnumerable<T> Collection)
		{
			return !Collection.Any();
		}

		private static TSource TryGetFirst<TSource>(this IEnumerable<TSource> Source, Func<TSource, bool> Predicate, out bool Found)
		{
			foreach (TSource item in Source)
			{
				if (Predicate(item))
				{
					Found = true;
					return item;
				}
			}
			Found = false;
			return default(TSource);
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "Sculas.BrutalCompanyAdditions";

		public const string PLUGIN_NAME = "BrutalCompanyAdditions";

		public const string PLUGIN_VERSION = "2.1.1";
	}
}
namespace BrutalCompanyAdditions.Patches
{
	public static class AIPatches
	{
		private static bool _patchFailed;

		[HarmonyPatch(typeof(MenuManager), "Start")]
		[HarmonyPrefix]
		public static void ShowPatchFailedMessage(MenuManager __instance)
		{
			if (!__instance.isInitScene && _patchFailed)
			{
				__instance.DisplayMenuNotification("[BrutalCompanyAdditions]\n\nA patch failed to apply. Report this issue together with your log file.", "[ Back ]");
				_patchFailed = false;
			}
		}

		[HarmonyPatch(typeof(Turret), "Update")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> TurretPlayerDamagePatch(IEnumerable<CodeInstruction> instructions)
		{
			FieldInfo healthField = AccessTools.Field(typeof(PlayerControllerB), "health");
			FieldInfo controllerField = AccessTools.Field(typeof(GameNetworkManager), "localPlayerController");
			int modified = 0;
			CodeInstruction lastInstruction = null;
			foreach (CodeInstruction instruction in instructions)
			{
				if (lastInstruction != null && modified < 2 && instruction.opcode == OpCodes.Ldc_I4_S && lastInstruction.opcode == OpCodes.Ldfld && (CodeInstructionExtensions.OperandIs(lastInstruction, (MemberInfo)healthField) || CodeInstructionExtensions.OperandIs(lastInstruction, (MemberInfo)controllerField)))
				{
					Plugin.Logger.LogInfo((object)$"Patching turret damage; m = {modified}, c = {instruction}, l = {lastInstruction}");
					modified++;
					lastInstruction = null;
					yield return instruction;
					yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(AIPatches), "GetTurretDamage", (Type[])null, (Type[])null));
				}
				else
				{
					lastInstruction = instruction;
					yield return instruction;
				}
			}
			if (modified != 2)
			{
				Plugin.Logger.LogError((object)$"Failed to patch turret damage! Please report this issue. ({modified} != {2})");
				_patchFailed = true;
			}
			else
			{
				Plugin.Logger.LogWarning((object)"Turret damage patched successfully!");
			}
		}

		public static int GetTurretDamage(int original)
		{
			if (!EventRegistry.GetEventByType<MovingTurrets>().IsActive())
			{
				return original;
			}
			return BCNetworkManager.Instance.TurretDamage.Value;
		}
	}
	public static class BCPatches
	{
		[HarmonyPatch(typeof(GameNetworkManager), "Start")]
		[HarmonyPostfix]
		private static void InjectNetworkManager()
		{
			NetworkManager.Singleton.AddNetworkPrefab(Plugin.BCNetworkManagerPrefab);
		}

		[HarmonyPatch(typeof(StartOfRound), "Awake")]
		[HarmonyPostfix]
		private static void SpawnNetworkManager()
		{
			//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)
			if (NetworkManager.Singleton.IsHost || NetworkManager.Singleton.IsServer)
			{
				Object.Instantiate<GameObject>(Plugin.BCNetworkManagerPrefab, Vector3.zero, Quaternion.identity).GetComponent<NetworkObject>().Spawn(false);
			}
		}

		[HarmonyPatch(typeof(RoundManager), "DespawnPropsAtEndOfRound")]
		[HarmonyPostfix]
		private static void HandleCustomEventEnd(ref RoundManager __instance)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected I4, but got Unknown
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			if (((NetworkBehaviour)__instance).IsHost)
			{
				EventEnum lastEvent = Utils.LastEvent;
				BCNetworkManager.Instance.ClearCurrentEvent((int)lastEvent);
				if (EventRegistry.IsCustomEvent(lastEvent))
				{
					IEvent @event = EventRegistry.GetEvent(lastEvent);
					Plugin.Logger.LogWarning((object)("Ending custom event " + @event.Name + "... (server)"));
					@event.OnEnd();
				}
			}
		}

		[HarmonyPatch(typeof(Plugin), "SelectRandomEvent")]
		[HarmonyPrefix]
		public static bool InjectCustomEventsServer(ref EventEnum __result)
		{
			//IL_000f: 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_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Expected I4, but got Unknown
			Plugin.Logger.LogWarning((object)"Injecting custom events... (server)");
			EventEnum val = Utils.SelectRandomEvent();
			if (EventRegistry.IsCustomEvent(val))
			{
				IEvent @event = EventRegistry.GetEvent(val);
				Plugin.Logger.LogWarning((object)("Selected custom event " + @event.Name));
			}
			else
			{
				Plugin.Logger.LogWarning((object)$"Selected original event {val}");
			}
			__result = (EventEnum)(int)val;
			return false;
		}

		[HarmonyPatch(typeof(Plugin), "HandleEventSpecificAdjustments")]
		[HarmonyPrefix]
		public static bool InjectEventHandlers(ref EventEnum eventEnum, ref SelectableLevel newLevel)
		{
			if (newLevel.sceneName == "CompanyBuilding")
			{
				Plugin.Logger.LogWarning((object)"Landed at The Company Building, skipping...");
				eventEnum = (EventEnum)0;
				return true;
			}
			if (!EventRegistry.IsCustomEvent(eventEnum))
			{
				Plugin.Logger.LogWarning((object)$"Event {eventEnum} is not a custom event, skipping...");
				return true;
			}
			IEvent @event = EventRegistry.GetEvent(eventEnum);
			Plugin.Logger.LogWarning((object)("Handling custom event " + @event.Name + "... (server)"));
			Utils.SendEventMessage(@event);
			@event.ExecuteServer(newLevel);
			BCNetworkManager.Instance.SetCurrentEvent((int)eventEnum, newLevel.levelID);
			return false;
		}
	}
	[HarmonyPatch(typeof(Terminal))]
	public class TerminalPatches
	{
		private const string ForceEventUsage = "Usage: forceevent [event name, partial allowed]";

		private static readonly string AllEventNames = "Available events: " + GeneralExtensions.Join<string>((IEnumerable<string>)EventRegistry.AllEvents.Keys, (Func<string, string>)null, ", ");

		[HarmonyPostfix]
		[HarmonyPatch("ParsePlayerSentence")]
		public static void BCTerminalParser(ref Terminal __instance, ref TerminalNode __result)
		{
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			string text = __instance.screenText.text;
			int textAdded = __instance.textAdded;
			int length = text.Length;
			int num = length - textAdded;
			(string, string) tuple = ParseCommand(text.Substring(num, length - num));
			string item = tuple.Item1;
			string item2 = tuple.Item2;
			string text2 = item;
			if (!(text2 == "forceevent"))
			{
				return;
			}
			if (((NetworkBehaviour)__instance).IsHost)
			{
				EventEnum SelectedEvent;
				if (string.IsNullOrWhiteSpace(item2))
				{
					string text3 = (Utils.IsEventForced ? ("Currently forced event: " + EventRegistry.GetEventName(Utils.ForcedEvent)) : "No event is currently forced.");
					Respond(out __result, text3 + "\n\nUsage: forceevent [event name, partial allowed]\n\n" + AllEventNames);
				}
				else if (!Utils.TryFindEventByName(item2, out SelectedEvent))
				{
					Respond(out __result, "Invalid event name: " + item2 + "\n\nUsage: forceevent [event name, partial allowed]\n\n" + AllEventNames);
				}
				else
				{
					Utils.ForcedEvent = SelectedEvent;
					Respond(out __result, "Forced next event to: " + EventRegistry.GetEventName(SelectedEvent));
				}
			}
			else if (!((NetworkBehaviour)__instance).IsHost)
			{
				Respond(out __result, "You must be the host to use this command!");
			}
		}

		private static (string, string) ParseCommand(string command)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			string[] array = command.ToLower().Split(' ');
			return (array[0], GeneralExtensions.Join<string>((IEnumerable<string>)array[Range.StartAt(Index.op_Implicit(1))], (Func<string, string>)null, " "));
		}

		private static void Respond(out TerminalNode node, string text, bool clearPreviousText = true)
		{
			node = ScriptableObject.CreateInstance<TerminalNode>();
			node.displayText = text + "\n\n\n";
			node.clearPreviousText = clearPreviousText;
		}
	}
}
namespace BrutalCompanyAdditions.Objects
{
	public class AICollisionDetect : MonoBehaviour
	{
		private const float DetectionRadius = 2.5f;

		private int _doorLayerMask;

		private Collider[] _doorColliders;

		public bool canOpenDoors = true;

		public float openDoorSpeedMultiplier = 1f;

		private void Start()
		{
			_doorLayerMask = LayerMask.GetMask(new string[1] { "InteractableObject" });
			_doorColliders = (Collider[])(object)new Collider[8];
		}

		private void FixedUpdate()
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			if (!canOpenDoors)
			{
				return;
			}
			int num = Physics.OverlapSphereNonAlloc(((Component)this).transform.position, 2.5f, _doorColliders, _doorLayerMask, (QueryTriggerInteraction)1);
			if (num == 0)
			{
				return;
			}
			DoorLock val = default(DoorLock);
			for (int i = 0; i < num; i++)
			{
				if (((Component)_doorColliders[i]).CompareTag("InteractTrigger") && ((Component)_doorColliders[i]).TryGetComponent<DoorLock>(ref val) && !val.isLocked && !val.isDoorOpened)
				{
					DoorLock obj = val;
					obj.enemyDoorMeter += Time.fixedDeltaTime * openDoorSpeedMultiplier;
					if (!(val.enemyDoorMeter <= 1f))
					{
						val.enemyDoorMeter = 0f;
						((Component)val).GetComponent<AnimatedObjectTrigger>().TriggerAnimationNonPlayer(false, true, false);
						val.OpenDoorAsEnemyServerRpc();
					}
				}
			}
		}
	}
	public class BCManager : MonoBehaviour
	{
		public static BCManager Instance { get; private set; }

		private void Awake()
		{
			Instance = this;
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
			Plugin.Logger.LogWarning((object)"BCManager initialized!");
		}

		public void ExecuteAfterDelay(Action Action, float Delay)
		{
			((MonoBehaviour)this).StartCoroutine(DelayedExecution(Action, Delay));
		}

		private static IEnumerator DelayedExecution(Action Action, float Delay)
		{
			yield return (object)new WaitForSeconds(Delay);
			Action();
		}
	}
	public class BCNetworkManager : NetworkBehaviour
	{
		private const string Tag = "[BCNetworkManager]";

		private readonly NetworkVariable<CurrentNetEvent> _currentEvent = new NetworkVariable<CurrentNetEvent>(default(CurrentNetEvent), (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0);

		public readonly NetworkVariable<int> TurretDamage = new NetworkVariable<int>(PluginConfig.TurretDamage.Value, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0);

		public static BCNetworkManager Instance { get; private set; }

		private void Awake()
		{
			Instance = this;
			Log("BCNetworkManager initialized!");
			NetworkVariable<CurrentNetEvent> currentEvent = _currentEvent;
			currentEvent.OnValueChanged = (OnValueChangedDelegate<CurrentNetEvent>)(object)Delegate.Combine((Delegate?)(object)currentEvent.OnValueChanged, (Delegate?)(object)new OnValueChangedDelegate<CurrentNetEvent>(OnCurrentEventChanged));
		}

		public void SetCurrentEvent(int EventId, int LevelId)
		{
			_currentEvent.Value = new CurrentNetEvent
			{
				EventId = EventId,
				LevelId = LevelId,
				IsEnding = false
			};
		}

		public void ClearCurrentEvent(int EventId)
		{
			int levelID = RoundManager.Instance.currentLevel.levelID;
			_currentEvent.Value = new CurrentNetEvent
			{
				EventId = EventId,
				LevelId = levelID,
				IsEnding = true
			};
		}

		private void OnCurrentEventChanged(CurrentNetEvent OldEvent, CurrentNetEvent NewEvent)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			if (((NetworkBehaviour)this).IsServer || OldEvent.Equals(NewEvent))
			{
				return;
			}
			Log($"Received new event: {NewEvent}, old event was {OldEvent}");
			Log("Injecting custom events... (client)");
			EventEnum eventId = (EventEnum)NewEvent.EventId;
			if (EventRegistry.IsCustomEvent(eventId))
			{
				IEvent @event = EventRegistry.GetEvent(eventId);
				if (NewEvent.IsEnding)
				{
					Log("Ending custom event " + @event.Name + "... (client)");
					@event.OnEnd();
				}
				else
				{
					Log("Handling custom event " + @event.Name + "... (client)");
					@event.ExecuteClient(StartOfRound.Instance.levels[NewEvent.LevelId]);
				}
			}
		}

		private static void Log(string Message)
		{
			Plugin.Logger.LogWarning((object)("[BCNetworkManager] " + Message));
		}

		protected override void __initializeVariables()
		{
			if (_currentEvent == null)
			{
				throw new Exception("BCNetworkManager._currentEvent cannot be null. All NetworkVariableBase instances must be initialized.");
			}
			((NetworkVariableBase)_currentEvent).Initialize((NetworkBehaviour)(object)this);
			((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)_currentEvent, "_currentEvent");
			base.NetworkVariableFields.Add((NetworkVariableBase)(object)_currentEvent);
			if (TurretDamage == null)
			{
				throw new Exception("BCNetworkManager.TurretDamage cannot be null. All NetworkVariableBase instances must be initialized.");
			}
			((NetworkVariableBase)TurretDamage).Initialize((NetworkBehaviour)(object)this);
			((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)TurretDamage, "TurretDamage");
			base.NetworkVariableFields.Add((NetworkVariableBase)(object)TurretDamage);
			((NetworkBehaviour)this).__initializeVariables();
		}

		protected internal override string __getTypeName()
		{
			return "BCNetworkManager";
		}
	}
	public struct CurrentNetEvent : INetworkSerializable, IEquatable<CurrentNetEvent>
	{
		public int EventId;

		public int LevelId;

		public bool IsEnding;

		public void NetworkSerialize<T>(BufferSerializer<T> Serializer) where T : IReaderWriter
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: 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_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: 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_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_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			if (Serializer.IsReader)
			{
				FastBufferReader fastBufferReader = Serializer.GetFastBufferReader();
				((FastBufferReader)(ref fastBufferReader)).ReadValueSafe<int>(ref EventId, default(ForPrimitives));
				((FastBufferReader)(ref fastBufferReader)).ReadValueSafe<int>(ref LevelId, default(ForPrimitives));
				((FastBufferReader)(ref fastBufferReader)).ReadValueSafe<bool>(ref IsEnding, default(ForPrimitives));
			}
			else
			{
				FastBufferWriter fastBufferWriter = Serializer.GetFastBufferWriter();
				((FastBufferWriter)(ref fastBufferWriter)).WriteValueSafe<int>(ref EventId, default(ForPrimitives));
				((FastBufferWriter)(ref fastBufferWriter)).WriteValueSafe<int>(ref LevelId, default(ForPrimitives));
				((FastBufferWriter)(ref fastBufferWriter)).WriteValueSafe<bool>(ref IsEnding, default(ForPrimitives));
			}
		}

		public bool Equals(CurrentNetEvent Other)
		{
			if (EventId == Other.EventId && LevelId == Other.LevelId)
			{
				return IsEnding == Other.IsEnding;
			}
			return false;
		}

		public override string ToString()
		{
			return $"(eid: {EventId}, lid: {LevelId}, ending: {IsEnding})";
		}
	}
	[RequireComponent(typeof(NavMeshAgent))]
	public class MovingTurretAI : NetworkBehaviour
	{
		private enum AIState
		{
			Roaming,
			Chasing
		}

		private const float AIIntervalTime = 0.2f;

		public const int DefaultPlayerDamage = 25;

		private const float PlayerLostIntervalTime = 0.075f;

		private const float PlayerLostMinTime = 1.5f;

		private const float PlayerLostMaxTime = -5f;

		private const float OpenDoorSpeedMultiplier = 0.5f;

		private const bool CanOpenDoorsWhileFiring = false;

		private const float AngularSpeed = 150f;

		private const float RoamingSpeed = 1.5f;

		private const float RoamingAcceleration = 4f;

		private const float ChasingSpeed = 2.5f;

		private const float ChasingAcceleration = 8f;

		private const float FiringSpeed = 0f;

		private const float FiringAcceleration = 0f;

		private const double RoamingCheckForPlayerIntervalTime = 0.05000000074505806;

		private const double ChasingCheckForPlayerIntervalTime = 0.07500000298023224;

		private const float RoamingRotationRange = 55f;

		private const float ChasingRotationRange = 65f;

		private const float UpdatePositionThreshold = 1f;

		private const float SyncMovementSpeed = 0.22f;

		private bool _showDebugText;

		private TextMesh _debugText;

		private GameObject _debugTextObject;

		private Vector3 _serverPosition;

		private Vector3 _tempVelocity;

		private float _previousYRotation;

		private float _targetYRotation;

		private NavMeshAgent _agent;

		private Turret _turret;

		private GameObject[] _aiNodes;

		private AICollisionDetect _collisionDetect;

		private double _updateAIInterval;

		private double _checkForPlayerInterval;

		private double _setDestinationToPlayerInterval;

		private AIState _aiState;

		private bool _hasTarget;

		private PlayerControllerB _targetedPlayer;

		private bool _lostPlayerInChase;

		private float _lastSeenTimer;

		private Vector3 _lastKnownPlayerPosition;

		private Collider[] _nearPlayerColliders;

		private Coroutine _searchCoroutine;

		private Coroutine _chooseTargetNodeCoroutine;

		private AISearchRoutine _currentSearch;

		private float _pathDistance;

		private NavMeshPath _path1;

		public override void OnDestroy()
		{
			((NetworkBehaviour)this).OnDestroy();
			Object.Destroy((Object)(object)_agent);
			if (_showDebugText)
			{
				Object.Destroy((Object)(object)_debugTextObject);
			}
		}

		private void Start()
		{
			//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_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Expected O, but got Unknown
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Expected O, but got Unknown
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Expected O, but got Unknown
			_serverPosition = ((Component)this).transform.position;
			_agent = ((Component)this).GetComponent<NavMeshAgent>();
			_turret = ((Component)this).GetComponentInChildren<Turret>();
			if (!((NetworkBehaviour)this).IsServer)
			{
				((Behaviour)_agent).enabled = false;
				return;
			}
			_collisionDetect = ((Component)_turret).gameObject.AddComponent<AICollisionDetect>();
			_collisionDetect.openDoorSpeedMultiplier = 0.5f;
			_agent.stoppingDistance = 0f;
			_agent.angularSpeed = 150f;
			_agent.radius = 1.21f;
			_agent.height = 3.3f;
			_agent.obstacleAvoidanceType = (ObstacleAvoidanceType)1;
			_agent.avoidancePriority = 50;
			_agent.areaMask = 31;
			_aiNodes = GameObject.FindGameObjectsWithTag("AINode");
			_currentSearch = new AISearchRoutine();
			_path1 = new NavMeshPath();
			_nearPlayerColliders = (Collider[])(object)new Collider[StartOfRound.Instance.allPlayerScripts.Length + 1];
			_showDebugText = PluginConfig.DebugAI.Value && ((NetworkBehaviour)this).IsServer;
			if (_showDebugText)
			{
				GameObject val = new GameObject("BCA AI Debug Text");
				val.transform.parent = _turret.aimPoint;
				val.transform.localPosition = new Vector3(0f, 0.5f, 0f);
				val.transform.localScale = new Vector3(0.5f, 0.5f, 0.5f);
				val.transform.rotation = Quaternion.Euler(0f, 90f, 0f);
				_debugTextObject = val;
				_debugText = _debugTextObject.AddComponent<TextMesh>();
				_debugText.fontSize = 100;
				_debugText.anchor = (TextAnchor)4;
			}
			StartRoaming();
		}

		private void Update()
		{
			//IL_0023: 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_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: 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_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02be: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c3: Invalid comparison between Unknown and I4
			//IL_03c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c9: Unknown result type (might be due to invalid IL or missing references)
			if (StartOfRound.Instance.livingPlayers == 0)
			{
				return;
			}
			if (!((NetworkBehaviour)this).IsServer)
			{
				Transform transform = ((Component)this).transform;
				((Component)this).transform.position = Vector3.SmoothDamp(transform.position, _serverPosition, ref _tempVelocity, 0.22f);
				Vector3 eulerAngles = transform.eulerAngles;
				((Vector3)(ref eulerAngles))..ctor(eulerAngles.x, Mathf.LerpAngle(eulerAngles.y, _targetYRotation, 15f * Time.deltaTime), eulerAngles.z);
				((Component)this).transform.eulerAngles = eulerAngles;
				return;
			}
			if (_showDebugText)
			{
				_debugText.text = $"{_aiState} (lostPlayer = {_lostPlayerInChase}, hasTarget = {_hasTarget})";
			}
			if (_hasTarget && (Object)(object)_targetedPlayer != (Object)null)
			{
				if (_setDestinationToPlayerInterval <= 0.0)
				{
					_setDestinationToPlayerInterval = 0.25;
					_agent.SetDestination(RoundManager.Instance.GetNavMeshPosition(((Component)_targetedPlayer).transform.position, RoundManager.Instance.navHit, 2.7f, -1));
				}
				else
				{
					Vector3 position = ((Component)_targetedPlayer).transform.position;
					_agent.SetDestination(new Vector3(position.x, _agent.destination.y, position.z));
					_setDestinationToPlayerInterval -= Time.deltaTime;
				}
			}
			if (!_turret.turretActive)
			{
				((Behaviour)_agent).enabled = false;
				return;
			}
			((Behaviour)_agent).enabled = true;
			if (_updateAIInterval >= 0.0)
			{
				_updateAIInterval -= Time.deltaTime;
			}
			else
			{
				SyncPositionToClients();
				DoAIInterval();
				_updateAIInterval = 0.20000000298023224;
			}
			if ((double)Mathf.Abs(_previousYRotation - ((Component)this).transform.eulerAngles.y) > 6.0)
			{
				_previousYRotation = ((Component)this).transform.eulerAngles.y;
				_targetYRotation = _previousYRotation;
				UpdateEnemyRotationClientRpc((short)_previousYRotation);
			}
			PlayerControllerB Player;
			switch (_aiState)
			{
			case AIState.Roaming:
				if (_checkForPlayerInterval <= 0.05000000074505806)
				{
					_checkForPlayerInterval += Time.deltaTime;
					break;
				}
				_checkForPlayerInterval = 0.0;
				if (CheckLineOfSightForPlayer(out Player, 55f, 3f, AngleRangeCheck: true))
				{
					StartChasing(Player);
				}
				break;
			case AIState.Chasing:
			{
				TurretMode turretMode = _turret.turretMode;
				if (turretMode - 2 <= 1)
				{
					SetAgentSpeed(0f, 0f);
					_collisionDetect.canOpenDoors = false;
				}
				else
				{
					SetAgentSpeed(2.5f, 8f);
					_collisionDetect.canOpenDoors = true;
				}
				if (_checkForPlayerInterval <= 0.07500000298023224)
				{
					_checkForPlayerInterval += Time.deltaTime;
					break;
				}
				_checkForPlayerInterval = 0.0;
				if (_lostPlayerInChase)
				{
					if (CheckLineOfSightForPlayer(out Player, 65f, 3f))
					{
						_lastSeenTimer = 0f;
						_lostPlayerInChase = false;
						SetTargetedPlayer(Player);
						break;
					}
					_lastSeenTimer -= 0.075f;
					if (!(_lastSeenTimer >= -5f))
					{
						StartRoaming();
					}
				}
				else if (CheckLineOfSightForPlayer(out Player, 65f, 3f))
				{
					_lastSeenTimer = 0f;
					_lastKnownPlayerPosition = ((Component)Player).transform.position;
					SetTargetedPlayer(Player);
				}
				else
				{
					_lastSeenTimer += 0.075f;
					if (!(_lastSeenTimer <= 1.5f))
					{
						_lostPlayerInChase = true;
					}
				}
				break;
			}
			default:
				throw new ArgumentOutOfRangeException();
			}
		}

		private void StartRoaming()
		{
			if (SetAIState(AIState.Roaming))
			{
				SetTargetedPlayer(null);
				_checkForPlayerInterval = 0.0;
				_lostPlayerInChase = false;
				_currentSearch.searchWidth = 25f;
				SetAgentSpeed();
			}
		}

		private void StartChasing(PlayerControllerB Player)
		{
			if (SetAIState(AIState.Chasing))
			{
				SetTargetedPlayer(Player);
				_checkForPlayerInterval = 0.0;
				_lostPlayerInChase = false;
				SetAgentSpeed(2.5f, 8f);
			}
		}

		private void DoAIInterval()
		{
			LogAI(() => "Starting AI interval");
			switch (_aiState)
			{
			case AIState.Roaming:
				AIRoaming();
				break;
			case AIState.Chasing:
				AIChasing();
				break;
			default:
				throw new ArgumentOutOfRangeException();
			}
		}

		private void AIRoaming()
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			if (!_currentSearch.inProgress)
			{
				LogAI(() => "Starting player search");
				StartSearch(((Component)this).transform.position);
			}
		}

		private void AIChasing()
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			CheckForVeryClosePlayer();
			if (_lostPlayerInChase)
			{
				if (!_currentSearch.inProgress)
				{
					_currentSearch.searchWidth = 30f;
					StartSearch(_lastKnownPlayerPosition);
					LogAI(() => "Lost player in chase, starting search at last known position");
				}
			}
			else if (_currentSearch.inProgress)
			{
				StopSearch(_currentSearch);
				LogAI(() => "Found player during chase, targeting player");
			}
		}

		private void OnSearchFinished()
		{
			_currentSearch.searchWidth = Mathf.Clamp(_currentSearch.searchWidth + 10f, 1f, 100f);
		}

		public void StartSearch(Vector3 StartOfSearch)
		{
			//IL_0026: 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_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			StopSearch(_currentSearch);
			if (_currentSearch == null)
			{
				_currentSearch = new AISearchRoutine();
			}
			_currentSearch.currentSearchStartPosition = StartOfSearch;
			if (_currentSearch.unsearchedNodes.IsEmpty())
			{
				_currentSearch.unsearchedNodes = _aiNodes.ToList();
			}
			_searchCoroutine = ((MonoBehaviour)this).StartCoroutine(PlayerSearchRoutine());
			_currentSearch.inProgress = true;
		}

		public void StopSearch(AISearchRoutine Search, bool Clear = true)
		{
			//IL_0065: 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)
			if (Search != null)
			{
				if (_searchCoroutine != null)
				{
					((MonoBehaviour)this).StopCoroutine(_searchCoroutine);
				}
				if (_chooseTargetNodeCoroutine != null)
				{
					((MonoBehaviour)this).StopCoroutine(_chooseTargetNodeCoroutine);
				}
				Search.calculatingNodeInSearch = false;
				Search.inProgress = false;
				if (Clear)
				{
					Search.unsearchedNodes = _aiNodes.ToList();
					Search.timesFinishingSearch = 0;
					Search.nodesEliminatedInCurrentSearch = 0;
					Search.currentTargetNode = null;
					Search.currentSearchStartPosition = Vector3.zero;
					Search.nextTargetNode = null;
					Search.choseTargetNode = false;
				}
			}
		}

		private IEnumerator PlayerSearchRoutine()
		{
			yield return null;
			while (_searchCoroutine != null)
			{
				yield return null;
				if (_currentSearch.unsearchedNodes.IsEmpty())
				{
					OnSearchFinished();
					if (!_currentSearch.loopSearch)
					{
						_currentSearch.inProgress = false;
						_currentSearch = null;
						break;
					}
					_currentSearch.unsearchedNodes = _aiNodes.ToList();
					AISearchRoutine currentSearch = _currentSearch;
					currentSearch.timesFinishingSearch++;
					_currentSearch.nodesEliminatedInCurrentSearch = 0;
					yield return (object)new WaitForSeconds(1f);
				}
				if (_currentSearch.choseTargetNode && _currentSearch.unsearchedNodes.Contains(_currentSearch.nextTargetNode))
				{
					_currentSearch.currentTargetNode = _currentSearch.nextTargetNode;
				}
				else
				{
					_currentSearch.waitingForTargetNode = true;
					StartCalculatingNextTargetNode();
					yield return (object)new WaitUntil((Func<bool>)(() => _currentSearch.choseTargetNode));
				}
				_currentSearch.waitingForTargetNode = false;
				if (_currentSearch.unsearchedNodes.IsEmpty() || (Object)(object)_currentSearch.currentTargetNode == (Object)null)
				{
					continue;
				}
				_currentSearch.unsearchedNodes.Remove(_currentSearch.currentTargetNode);
				_agent.SetDestination(RoundManager.Instance.GetNavMeshPosition(_currentSearch.currentTargetNode.transform.position, RoundManager.Instance.navHit, -1f, -1));
				int i = _currentSearch.unsearchedNodes.Count - 1;
				while (i >= 0)
				{
					if ((double)Vector3.Distance(_currentSearch.currentTargetNode.transform.position, _currentSearch.unsearchedNodes[i].transform.position) < (double)_currentSearch.searchPrecision)
					{
						EliminateNodeFromSearch(i);
					}
					if (i % 10 == 0)
					{
						yield return null;
					}
					int num = i - 1;
					i = num;
				}
				StartCalculatingNextTargetNode();
				int timeSpent = 0;
				while (_searchCoroutine != null)
				{
					int num = timeSpent + 1;
					timeSpent = num;
					if (num >= 32)
					{
						break;
					}
					yield return (object)new WaitForSeconds(0.5f);
					if ((double)Vector3.Distance(((Component)this).transform.position, _currentSearch.currentTargetNode.transform.position) < (double)_currentSearch.searchPrecision)
					{
						break;
					}
				}
			}
		}

		private void StartCalculatingNextTargetNode()
		{
			if (_chooseTargetNodeCoroutine == null)
			{
				_currentSearch.choseTargetNode = false;
				_chooseTargetNodeCoroutine = ((MonoBehaviour)this).StartCoroutine(ChooseNextNodeInSearchRoutine());
			}
			else if (!_currentSearch.calculatingNodeInSearch)
			{
				_currentSearch.choseTargetNode = false;
				_currentSearch.calculatingNodeInSearch = true;
				((MonoBehaviour)this).StopCoroutine(_chooseTargetNodeCoroutine);
				_chooseTargetNodeCoroutine = ((MonoBehaviour)this).StartCoroutine(ChooseNextNodeInSearchRoutine());
			}
		}

		private IEnumerator ChooseNextNodeInSearchRoutine()
		{
			yield return null;
			float closestDist = 500f;
			GameObject chosenNode = null;
			int i = _currentSearch.unsearchedNodes.Count - 1;
			while (i >= 0)
			{
				if (i % 5 == 0)
				{
					yield return null;
				}
				if (Vector3.Distance(_currentSearch.currentSearchStartPosition, _currentSearch.unsearchedNodes[i].transform.position) > _currentSearch.searchWidth)
				{
					EliminateNodeFromSearch(i);
				}
				else if (PathIsIntersectedByLineOfSight(_currentSearch.unsearchedNodes[i].transform.position, CalculatePathDistance: true, AvoidLineOfSight: false))
				{
					EliminateNodeFromSearch(i);
				}
				else if (_pathDistance < closestDist)
				{
					closestDist = _pathDistance;
					chosenNode = _currentSearch.unsearchedNodes[i];
				}
				int num = i - 1;
				i = num;
			}
			if (_currentSearch.waitingForTargetNode)
			{
				_currentSearch.currentTargetNode = chosenNode;
			}
			else
			{
				_currentSearch.nextTargetNode = chosenNode;
			}
			_currentSearch.choseTargetNode = true;
			_currentSearch.calculatingNodeInSearch = false;
			_chooseTargetNodeCoroutine = null;
		}

		private bool PathIsIntersectedByLineOfSight(Vector3 TargetPos, bool CalculatePathDistance = false, bool AvoidLineOfSight = true)
		{
			//IL_0011: 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_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			_pathDistance = 0f;
			if (!_agent.CalculatePath(TargetPos, _path1))
			{
				return true;
			}
			if ((double)Vector3.Distance(_path1.corners[^1], RoundManager.Instance.GetNavMeshPosition(TargetPos, RoundManager.Instance.navHit, 2.7f, -1)) > 1.5)
			{
				return true;
			}
			if (CalculatePathDistance)
			{
				for (int i = 1; i < _path1.corners.Length; i++)
				{
					_pathDistance += Vector3.Distance(_path1.corners[i - 1], _path1.corners[i]);
					if (AvoidLineOfSight && Physics.Linecast(_path1.corners[i - 1], _path1.corners[i], 262144))
					{
						return true;
					}
				}
			}
			else if (AvoidLineOfSight)
			{
				for (int j = 1; j < _path1.corners.Length; j++)
				{
					if (Physics.Linecast(_path1.corners[j - 1], _path1.corners[j], 262144))
					{
						return true;
					}
				}
			}
			return false;
		}

		public void SyncPositionToClients()
		{
			//IL_0001: 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_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			if (!(Vector3.Distance(_serverPosition, ((Component)this).transform.position) <= 1f))
			{
				_serverPosition = ((Component)this).transform.position;
				UpdateEnemyPositionClientRpc(_serverPosition);
			}
		}

		[ClientRpc]
		private void UpdateEnemyPositionClientRpc(Vector3 NewPosition)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost))
				{
					ClientRpcParams val = default(ClientRpcParams);
					FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(2743561777u, val, (RpcDelivery)0);
					((FastBufferWriter)(ref val2)).WriteValueSafe(ref NewPosition);
					((NetworkBehaviour)this).__endSendClientRpc(ref val2, 2743561777u, val, (RpcDelivery)0);
				}
				if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost))
				{
					_serverPosition = NewPosition;
				}
			}
		}

		[ClientRpc]
		private void UpdateEnemyRotationClientRpc(short RotationY)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost))
				{
					ClientRpcParams val = default(ClientRpcParams);
					FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(1780689525u, val, (RpcDelivery)0);
					BytePacker.WriteValueBitPacked(val2, RotationY);
					((NetworkBehaviour)this).__endSendClientRpc(ref val2, 1780689525u, val, (RpcDelivery)0);
				}
				if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost))
				{
					_previousYRotation = ((Component)this).transform.eulerAngles.y;
					_targetYRotation = RotationY;
				}
			}
		}

		private void SetAgentSpeed(float Speed = 1.5f, float Acceleration = 4f)
		{
			_agent.speed = Speed;
			_agent.acceleration = Acceleration;
		}

		private bool CheckLineOfSightForPlayer(out PlayerControllerB Player, float Width, float Radius = 2f, bool AngleRangeCheck = false)
		{
			_turret.rotationRange = Width;
			Player = _turret.CheckForPlayersInLineOfSight(Radius, AngleRangeCheck);
			return (Object)(object)Player != (Object)null;
		}

		private void CheckForVeryClosePlayer()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: 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_006c: Unknown result type (might be due to invalid IL or missing references)
			PlayerControllerB val = default(PlayerControllerB);
			if (Physics.OverlapSphereNonAlloc(((Component)this).transform.position, 1.5f, _nearPlayerColliders, 8, (QueryTriggerInteraction)1) > 0 && ((Component)((Component)_nearPlayerColliders[0]).transform).TryGetComponent<PlayerControllerB>(ref val) && !((Object)(object)val == (Object)(object)_targetedPlayer) && !Physics.Linecast(((Component)this).transform.position + Vector3.up * 0.3f, ((Component)val).transform.position, StartOfRound.Instance.collidersAndRoomMask))
			{
				SetTargetedPlayer(val);
			}
		}

		private void EliminateNodeFromSearch(int Index)
		{
			_currentSearch.unsearchedNodes.RemoveAt(Index);
			AISearchRoutine currentSearch = _currentSearch;
			currentSearch.nodesEliminatedInCurrentSearch++;
		}

		private bool SetAIState(AIState State)
		{
			if (_aiState == State)
			{
				return false;
			}
			_aiState = State;
			LogAI(() => $"Setting AI state to {State}");
			return true;
		}

		private void SetTargetedPlayer([CanBeNull] PlayerControllerB Player)
		{
			_targetedPlayer = Player;
			_hasTarget = (Object)(object)Player != (Object)null;
			LogAI(() => $"Setting targeted player to {Player}");
		}

		private void LogAI(Func<string> Message)
		{
			if (PluginConfig.DebugAILogging.Value)
			{
				Plugin.Logger.LogInfo((object)string.Format("[{0}] (state = {1}) {2}", "MovingTurretAI", _aiState, Message()));
			}
		}

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

		[RuntimeInitializeOnLoadMethod]
		internal static void InitializeRPCS_MovingTurretAI()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			NetworkManager.__rpc_func_table.Add(2743561777u, new RpcReceiveHandler(__rpc_handler_2743561777));
			NetworkManager.__rpc_func_table.Add(1780689525u, new RpcReceiveHandler(__rpc_handler_1780689525));
		}

		private static void __rpc_handler_2743561777(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				Vector3 newPosition = default(Vector3);
				((FastBufferReader)(ref reader)).ReadValueSafe(ref newPosition);
				target.__rpc_exec_stage = (__RpcExecStage)2;
				((MovingTurretAI)(object)target).UpdateEnemyPositionClientRpc(newPosition);
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		private static void __rpc_handler_1780689525(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				short rotationY = default(short);
				ByteUnpacker.ReadValueBitPacked(reader, ref rotationY);
				target.__rpc_exec_stage = (__RpcExecStage)2;
				((MovingTurretAI)(object)target).UpdateEnemyRotationClientRpc(rotationY);
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		protected internal override string __getTypeName()
		{
			return "MovingTurretAI";
		}
	}
}
namespace BrutalCompanyAdditions.Events
{
	public class BlingBling : IEvent
	{
		public string Name => "Bling bling";

		public string Description => "So many gold bars! ...right?";

		public EventPositivity Positivity => EventPositivity.Neutral;

		public void ExecuteServer(SelectableLevel Level)
		{
			Level.ReplaceScrap("Gold bar", 100, 1, 10);
		}

		public void ExecuteClient(SelectableLevel Level)
		{
		}

		public void OnEnd()
		{
		}
	}
	public interface IEvent
	{
		string Name { get; }

		string Description { get; }

		EventPositivity Positivity { get; }

		void ExecuteServer(SelectableLevel Level);

		void ExecuteClient(SelectableLevel Level);

		void OnEnd();
	}
	public enum EventPositivity
	{
		Positive,
		Neutral,
		Negative,
		Golden
	}
	public class MovingTurrets : IEvent
	{
		private GameObject _turretPrefab;

		public string Name => "Since when can they move?!";

		public string Description => "Did someone give them wheels?";

		public EventPositivity Positivity => EventPositivity.Negative;

		public void ExecuteServer(SelectableLevel Level)
		{
			BCNetworkManager.Instance.TurretDamage.Value = PluginConfig.TurretDamage.Value;
			Execute(Level);
		}

		public void ExecuteClient(SelectableLevel Level)
		{
			Execute(Level);
		}

		private void Execute(SelectableLevel Level)
		{
			SpawnableMapObject[] spawnableMapObjects = Level.spawnableMapObjects;
			foreach (SpawnableMapObject val in spawnableMapObjects)
			{
				if (val.IsObjectTypeOf<Turret>(out var _))
				{
					(_turretPrefab = val.prefabToSpawn).AddComponent<MovingTurretAI>();
					break;
				}
			}
		}

		public void OnEnd()
		{
			if (!((Object)(object)_turretPrefab == (Object)null))
			{
				MovingTurretAI component = _turretPrefab.GetComponent<MovingTurretAI>();
				if ((Object)(object)component != (Object)null)
				{
					Object.Destroy((Object)(object)component);
				}
			}
		}
	}
	public class TheVault : IEvent
	{
		public string Name => "Got any stock?";

		public string Description => "They used to say Fort Knox was buried here...";

		public EventPositivity Positivity => EventPositivity.Golden;

		public void ExecuteServer(SelectableLevel Level)
		{
			Level.ReplaceScrap("Gold bar", 100, 100, 350);
		}

		public void ExecuteClient(SelectableLevel Level)
		{
		}

		public void OnEnd()
		{
		}
	}
}