Decompiled source of Overworked v1.1.1

Overworked.dll

Decompiled 9 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Overworked.Core;
using Overworked.Core.Creatures.HoarderBug;
using Overworked.Core.CustomTerminal;
using Overworked.Core.Levels;
using Overworked.Core.Patches;
using Overworked.Core.Placement;
using Overworked.Core.Scanner;
using Overworked.Core.Selling;
using Unity.Netcode;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Overworked")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Overworked")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyInformationalVersion("1.1.0+ab047318a31c4cc88a99e75a832c7cc07bffdeaf")]
[assembly: AssemblyProduct("Overworked")]
[assembly: AssemblyTitle("Overworked")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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 Overworked
{
	[BepInPlugin("dev.timmywastor.overworked", "Overworked", "1.1.0")]
	public class Plugin : BaseUnityPlugin
	{
		public const string ModGUID = "dev.timmywastor.overworked";

		public const string ModName = "Overworked";

		public const string ModVersion = "1.1.0";

		public static Harmony Harmony = new Harmony("dev.timmywastor.overworked");

		public static ManualLogSource OverworkedLogger;

		public static string PluginFolder;

		private void Awake()
		{
			string location = ((BaseUnityPlugin)this).Info.Location;
			PluginFolder = Path.GetDirectoryName(location);
			OverworkedLogger = ((BaseUnityPlugin)this).Logger;
			OverworkedCore.Initialize();
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "Overworked";

		public const string PLUGIN_NAME = "Overworked";

		public const string PLUGIN_VERSION = "1.1.0";
	}
}
namespace Overworked.Core
{
	internal class OverworkedCore
	{
		public static void Initialize()
		{
			Patch();
		}

		private static void Patch()
		{
			Plugin.Harmony.PatchAll(typeof(PlayerControllerBPatch));
			Plugin.Harmony.PatchAll(typeof(RoundManagerPatch));
			Plugin.Harmony.PatchAll(typeof(GameNetworkManagerPatch));
			Plugin.Harmony.PatchAll(typeof(StartOfRoundPatch));
			Plugin.Harmony.PatchAll(typeof(GrabbableObjectPatch));
			Plugin.Harmony.PatchAll(typeof(OverworkedTerminal));
			Plugin.Harmony.PatchAll(typeof(HoarderBugController));
		}
	}
}
namespace Overworked.Core.Selling
{
	internal class SellingModule
	{
		private const string _moneyFieldName = "Ow_money";

		private static Terminal _currentTerminal;

		private static int _money = 0;

		private static readonly string helpHost = ">MOONS\r\nTo see the list of moons the autopilot can route to.\r\n\r\n>STORE\r\nTo see the company store's selection of useful items.\r\n\r\n>BESTIARY\r\nTo see the list of wildlife on record.\r\n\r\n>STORAGE\r\nTo access objects placed into storage.\r\n\r\n>STOCK\r\nStore and manipulate your scrap.\r\n\r\n>OTHER\r\nTo see the list of other commands\r\n\r\n[numberOfItemsOnRoute]\r\n";

		private static readonly string helpClient = ">MOONS\r\nTo see the list of moons the autopilot can route to.\r\n\r\n>STORE\r\nTo see the company store's selection of useful items.\r\n\r\n>BESTIARY\r\nTo see the list of wildlife on record.\r\n\r\n>STORAGE\r\nTo access objects placed into storage.\r\n\r\n>OTHER\r\nTo see the list of other commands\r\n\r\n[numberOfItemsOnRoute]\r\n";

		private static readonly string commands = ">STOCK [scrap]\nStocks all the available ship scrap.\n\n>STOCK [view] [-S](OPTIONAL,shares it to the chat)\nCheck how much scrap value is stored.\n\n>STOCK SELL [amount]\nAllows you to sell your stored scrap value at the company building.\n\n";

		private static readonly string stockMessage = "Welcome to STOCK™.\nuse the following commands to manipulate your stock.\n----------------------------\n\n" + commands;

		private static readonly string stockScrapMessage = "You have requested to stock all the available ship scrap.\n\nPlease CONFIRM or DENY";

		private static readonly string[] _blacklistedItems = new string[3] { "Shotgun", "Ammo", "Kitchen knife" };

		private static MethodInfo AddTextMessageServerRpc = AccessTools.Method(typeof(HUDManager), "AddTextMessageServerRpc", (Type[])null, (Type[])null);

		private static MethodInfo SellAndDisplayItemProfits = AccessTools.Method(typeof(DepositItemsDesk), "SellAndDisplayItemProfits", (Type[])null, (Type[])null);

		private static IEnumerator ShowTipDelayed()
		{
			yield return (object)new WaitForSeconds(2f);
			HUDManager.Instance.DisplayTip("Overworked", "Scrap stocking module initialized, type 'stock' on the terminal for the list of commands.", false, false, "");
		}

		public static void Initialize(Terminal t)
		{
			if (((NetworkBehaviour)StartOfRound.Instance).IsHost)
			{
				((MonoBehaviour)t).StartCoroutine(ShowTipDelayed());
				t.terminalNodes.allKeywords[5].specialKeywordResult.displayText = helpHost;
				_currentTerminal = t;
				_money = 0;
				InjectCommands();
				Load();
			}
			else
			{
				t.terminalNodes.allKeywords[5].specialKeywordResult.displayText = helpClient;
			}
		}

		public static void ResetMoney()
		{
			_money = 0;
		}

		private static void Load()
		{
			string currentSaveFileName = GameNetworkManager.Instance.currentSaveFileName;
			if (ES3.KeyExists("Ow_money", currentSaveFileName))
			{
				_money = ES3.Load<int>("Ow_money", currentSaveFileName);
			}
		}

		public static void Save()
		{
			string currentSaveFileName = GameNetworkManager.Instance.currentSaveFileName;
			ES3.Save<int>("Ow_money", _money, currentSaveFileName);
		}

		private static void GetMoneyAndUpdate()
		{
			int num = _money;
			GrabbableObject[] array = Object.FindObjectsOfType<GrabbableObject>();
			GrabbableObject[] array2 = array;
			foreach (GrabbableObject val in array2)
			{
				if (val.itemProperties.isScrap && !_blacklistedItems.Contains(val.itemProperties.itemName) && ((NetworkBehaviour)val).IsSpawned && val.isInShipRoom && !val.isHeld)
				{
					num += val.scrapValue;
					((NetworkBehaviour)val).NetworkObject.Despawn(true);
				}
			}
			_money = num;
		}

		public static void SendMessage(string text)
		{
			AddTextMessageServerRpc.Invoke(HUDManager.Instance, new object[1] { text });
		}

		private static bool StockSell(int sellAmountParsed)
		{
			DepositItemsDesk val = Object.FindObjectOfType<DepositItemsDesk>();
			int num = (int)((float)sellAmountParsed * StartOfRound.Instance.companyBuyingRate);
			if (sellAmountParsed <= 0 || sellAmountParsed > _money)
			{
				return false;
			}
			Terminal currentTerminal = _currentTerminal;
			currentTerminal.groupCredits += num;
			val.SellItemsClientRpc(num, _currentTerminal.groupCredits, 0, StartOfRound.Instance.companyBuyingRate);
			SellAndDisplayItemProfits.Invoke(val, new object[2] { num, _currentTerminal.groupCredits });
			_money -= sellAmountParsed;
			return true;
		}

		private static void InjectCommands()
		{
			TerminalCommand stockCommand = new TerminalCommand("stock");
			int currentSellAmount = 0;
			string currentSellMessage = "";
			stockCommand.AddState("default", delegate(string[] args)
			{
				if (args.Length > 1)
				{
					switch (args[1])
					{
					case "scrap":
						stockCommand.MoveTo("scrap");
						return stockScrapMessage;
					case "view":
						if (args.Length > 2 && OverworkedTerminal.Match(args[2], "-share"))
						{
							SendMessage($"<mark=#000000><color=#00FF00>Terminal/Stock™: ${_money}</mark></color>");
						}
						stockCommand.Finish();
						return $"You have obtained ${_money} worth of scrap.";
					case "sell":
					{
						if (args.Length > 2 && int.TryParse(args[2], out var result) && result > 0)
						{
							DepositItemsDesk val = Object.FindObjectOfType<DepositItemsDesk>();
							if ((Object)(object)val == (Object)null)
							{
								stockCommand.Finish();
								return "You must route and land to the company building to sell your stocked scrap.";
							}
							currentSellAmount = result;
							currentSellMessage = $"You have requested to sell ${currentSellAmount} of stocked scrap value.\n\nPlease CONFIRM or DENY";
							stockCommand.MoveTo("sell");
							return currentSellMessage;
						}
						stockCommand.Finish();
						return "Invalid amount of scrap value to sell detected, protocol aborted.";
					}
					}
				}
				stockCommand.Finish();
				return stockMessage;
			});
			stockCommand.AddState("sell", delegate(string[] args)
			{
				DepositItemsDesk val = Object.FindObjectOfType<DepositItemsDesk>();
				if ((Object)(object)val != (Object)null)
				{
					if (OverworkedTerminal.Match(args[0], "confirm"))
					{
						stockCommand.Finish();
						if (StockSell(currentSellAmount))
						{
							_currentTerminal.PlayTerminalAudioServerRpc(0);
							SendMessage($"{GameNetworkManager.Instance.localPlayerController.playerUsername} sold <color=#3AFF61>${currentSellAmount}</color>.");
							return $"Successfully sold ${currentSellAmount}! Your work keeps the company happy.";
						}
						return $"You do not have enough stock value to sell ${currentSellAmount}";
					}
					if (OverworkedTerminal.Match(args[0], "deny"))
					{
						stockCommand.Finish();
						return "You have cancelled the selling protocol.";
					}
					return currentSellMessage;
				}
				stockCommand.Finish();
				return "You must route and land to the company building to sell your stocked scrap.";
			});
			stockCommand.AddState("scrap", delegate(string[] args)
			{
				if (StartOfRound.Instance.inShipPhase)
				{
					if (OverworkedTerminal.Match(args[0], "confirm"))
					{
						stockCommand.Finish();
						GetMoneyAndUpdate();
						_currentTerminal.PlayTerminalAudioServerRpc(2);
						SendMessage(GameNetworkManager.Instance.localPlayerController.playerUsername + " stocked the ship scrap.");
						return $"Successfully stocked the ship scrap, your new balance is ${_money}.";
					}
					if (OverworkedTerminal.Match(args[0], "deny"))
					{
						stockCommand.Finish();
						return "You have cancelled the ship stocking protocol.";
					}
					return stockScrapMessage;
				}
				stockCommand.Finish();
				return "Cannot stock scrap while the ship isn't in orbit.";
			});
			OverworkedTerminal.AddCommand(stockCommand);
		}
	}
}
namespace Overworked.Core.Scanner
{
	internal struct ScanData
	{
		public int shipValue;

		public int outdoorValue;

		public int indoorValue;

		public int shipScrapAmount;

		public int outdoorScrapAmount;

		public int indoorScrapAmount;

		public bool foundEggs;

		public bool foundHives;

		public ScanData()
		{
			shipValue = 0;
			outdoorValue = 0;
			indoorValue = 0;
			shipScrapAmount = 0;
			outdoorScrapAmount = 0;
			indoorScrapAmount = 0;
			foundEggs = false;
			foundHives = false;
		}
	}
	internal class Scan
	{
		private static ScanData RunScan()
		{
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			GrabbableObject[] array = Object.FindObjectsOfType<GrabbableObject>();
			ScanData result = new ScanData();
			GrabbableObject[] array2 = array;
			foreach (GrabbableObject val in array2)
			{
				if (val.itemProperties.itemName == "Body")
				{
					continue;
				}
				if (val.itemProperties.itemName == "Egg" && !val.isInShipRoom)
				{
					result.foundEggs = true;
				}
				if (val.itemProperties.itemName == "Hive" && !val.isInShipRoom)
				{
					result.foundHives = true;
				}
				if (val.itemProperties.isScrap && !val.isInShipRoom)
				{
					if (((Component)val).transform.position.y < -80f)
					{
						result.indoorValue += val.scrapValue;
						result.indoorScrapAmount++;
					}
					else
					{
						result.outdoorValue += val.scrapValue;
						result.outdoorScrapAmount++;
					}
				}
				else if (val.itemProperties.isScrap)
				{
					result.shipValue += val.scrapValue;
					result.shipScrapAmount++;
				}
			}
			return result;
		}

		public static void Initialize(Terminal t)
		{
			TerminalCommand scanCommand = new TerminalCommand("scan");
			scanCommand.AddState("default", delegate(string[] args)
			{
				ScanData scanData = RunScan();
				if (args.Length > 1 && OverworkedTerminal.Match(args[1], "-share"))
				{
					SellingModule.SendMessage($"<mark=#000000><color=#00FF00>Terminal/Scan: {scanData.indoorScrapAmount} {scanData.outdoorScrapAmount}</mark></color>");
				}
				scanCommand.Finish();
				return string.Format("The ship scanners have detected the following:\n\n* Ship value: ${0} ({1} items)\n* Outdoor value: ${2} ({3} items)\n* Indoor value: ${4} ({5} items){6}{7}\n\nFor a total of {8} items outside.", scanData.shipValue, scanData.shipScrapAmount, scanData.outdoorValue, scanData.outdoorScrapAmount, scanData.indoorValue, scanData.indoorScrapAmount, scanData.foundEggs ? "\n\nA giant bird like creature seems to have nested on the exomoon." : "", scanData.foundHives ? "\n\nDangerous insect life seems to live in harmony with the ecosystem." : "", scanData.indoorScrapAmount + scanData.outdoorScrapAmount);
			});
			OverworkedTerminal.AddCommand(scanCommand);
		}
	}
}
namespace Overworked.Core.Placement
{
	internal class ItemPlacement
	{
		private static readonly Dictionary<string, Vector3> placements = new Dictionary<string, Vector3>
		{
			{
				"Pro-flashlight",
				new Vector3(7.7134f, 1f, -14.1152f)
			},
			{
				"Flashlight",
				new Vector3(7.7134f, 0.3565f, -14.1152f)
			},
			{
				"Shovel",
				new Vector3(5.7842f, 0.3817f, -14.9624f)
			},
			{
				"Lockpicker",
				new Vector3(6.6094f, 0.3796f, -14.103f)
			},
			{
				"Weed killer",
				new Vector3(5.3645f, 0.7417f, -14.1853f)
			},
			{
				"Spray paint",
				new Vector3(4.6839f, 0.3617f, -13.9803f)
			},
			{
				"Walkie-talkie",
				new Vector3(4.1293f, 0.3417f, -14.1254f)
			},
			{
				"Stun grenade",
				new Vector3(3.4229f, 0.3009f, -13.9947f)
			},
			{
				"Extension ladder",
				new Vector3(7.8912f, 0.396f, -13.0898f)
			},
			{
				"Belt bag",
				new Vector3(6.547f, 0.6398f, -12.9742f)
			},
			{
				"Jetpack",
				new Vector3(5.6698f, 0.4417f, -13.0838f)
			},
			{
				"Key",
				new Vector3(4.0051f, 0.3117f, -13.084f)
			},
			{
				"Shotgun",
				new Vector3(4.7607f, 0.323f, -15.0969f)
			},
			{
				"Ammo",
				new Vector3(4.1876f, 0.4307f, -15.0332f)
			},
			{
				"Kitchen knife",
				new Vector3(5.0984f, 0.3517f, -13.1254f)
			}
		};

		public static void ReplaceItems()
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			GrabbableObject[] array = Object.FindObjectsOfType<GrabbableObject>();
			GrabbableObject[] array2 = array;
			foreach (GrabbableObject val in array2)
			{
				if (placements.TryGetValue(val.itemProperties.itemName, out var value))
				{
					((Component)val).gameObject.transform.position = value;
				}
			}
		}
	}
}
namespace Overworked.Core.Patches
{
	[HarmonyPatch(typeof(PlayerControllerB))]
	internal class PlayerControllerBPatch
	{
		[HarmonyPatch("Update")]
		[HarmonyPostfix]
		private static void Update_Postfix(PlayerControllerB __instance)
		{
			if (__instance.isInsideFactory && RoundManager.Instance.currentDungeonType == 4)
			{
				__instance.hinderedMultiplier = 0.5f;
			}
		}
	}
	[HarmonyPatch(typeof(RoundManager))]
	internal class RoundManagerPatch
	{
		[HarmonyPatch("LoadNewLevel")]
		[HarmonyPrefix]
		private static void LoadNewLevel_Prefix(ref SelectableLevel newLevel)
		{
			LevelLoading.ApplyLevelData(newLevel);
		}
	}
	[HarmonyPatch(typeof(StartOfRound))]
	internal class StartOfRoundPatch
	{
		[HarmonyPatch("EndOfGame")]
		[HarmonyPrefix]
		private static void EndOfGame_Prefix(StartOfRound __instance)
		{
			if (((NetworkBehaviour)StartOfRound.Instance).IsHost && __instance.allPlayersDead)
			{
				SellingModule.ResetMoney();
			}
		}

		[HarmonyPatch("LoadShipGrabbableItems")]
		[HarmonyPostfix]
		private static void LoadShipGrabbableItems_Postfix(StartOfRound __instance)
		{
			ItemPlacement.ReplaceItems();
		}
	}
	[HarmonyPatch(typeof(GameNetworkManager))]
	internal class GameNetworkManagerPatch
	{
		[HarmonyPatch("SaveGameValues")]
		[HarmonyPrefix]
		private static void SaveGame_Prefix(GameNetworkManager __instance)
		{
			if (((NetworkBehaviour)StartOfRound.Instance).IsHost && StartOfRound.Instance.inShipPhase)
			{
				SellingModule.Save();
			}
		}
	}
	[HarmonyPatch(typeof(GrabbableObject))]
	internal class GrabbableObjectPatch
	{
		[HarmonyPatch("Start")]
		[HarmonyPostfix]
		private static void Start_Postfix(GrabbableObject __instance)
		{
			__instance.itemProperties.canBeGrabbedBeforeGameStart = true;
		}
	}
}
namespace Overworked.Core.Levels
{
	internal class LevelLoading
	{
		public static void ApplyLevelData(SelectableLevel newLevel)
		{
			string planetName = newLevel.PlanetName;
			string text = planetName;
			string text2 = text;
			if (!(text2 == "20 Adamance"))
			{
				if (text2 == "68 Artifice")
				{
					newLevel.maxScrap = 37;
					newLevel.minScrap = 31;
				}
			}
			else
			{
				newLevel.maxScrap = 18;
				newLevel.minScrap = 16;
			}
			foreach (SpawnableEnemyWithRarity enemy in newLevel.Enemies)
			{
				string enemyName = enemy.enemyType.enemyName;
				if (enemyName == "Cadaver Growths" && planetName == "20 Adamance")
				{
					enemy.rarity = 0;
				}
			}
		}
	}
}
namespace Overworked.Core.CustomTerminal
{
	internal class TerminalCommand
	{
		public bool ShouldUnfocus = false;

		public string Keyword { get; }

		public string CommandState { get; private set; } = "default";

		public Dictionary<string, Func<string[], string>> RegisteredStates { get; } = new Dictionary<string, Func<string[], string>>();

		public TerminalCommand(string keyword)
		{
			Keyword = keyword.ToLower();
		}

		public void AddState(string stateName, Func<string[], string> newState)
		{
			RegisteredStates[stateName] = newState;
		}

		public void MoveTo(string state)
		{
			if (RegisteredStates.ContainsKey(state))
			{
				CommandState = state;
			}
		}

		public void Finish()
		{
			ShouldUnfocus = true;
			CommandState = "default";
		}
	}
	[HarmonyPatch(typeof(Terminal))]
	internal class OverworkedTerminal
	{
		private static List<TerminalCommand> _commands = new List<TerminalCommand>();

		private static TerminalNode _resultNode = new TerminalNode();

		private static TerminalCommand _focusedCommand;

		public static void AddCommand(TerminalCommand newCommand)
		{
			_commands.Add(newCommand);
		}

		public static bool Match(string input, string compare)
		{
			if (input.Length > compare.Length)
			{
				return false;
			}
			return compare.StartsWith(input, StringComparison.OrdinalIgnoreCase);
		}

		[HarmonyPatch("ParsePlayerSentence")]
		[HarmonyPrefix]
		private static bool ParsePlayerSentence(Terminal __instance, ref TerminalNode __result)
		{
			string text = __instance.screenText.text.Substring(__instance.screenText.text.Length - __instance.textAdded);
			string[] array = text.Split(" ", StringSplitOptions.RemoveEmptyEntries);
			if (array.Length == 0)
			{
				return true;
			}
			string firstArgument = array[0].ToLower();
			if (_focusedCommand == null)
			{
				_focusedCommand = _commands.FirstOrDefault((TerminalCommand c) => c.Keyword == firstArgument);
			}
			if (_focusedCommand == null)
			{
				return true;
			}
			Func<string[], string> func = _focusedCommand.RegisteredStates[_focusedCommand.CommandState];
			string text2 = func(array);
			if (_focusedCommand.ShouldUnfocus)
			{
				_focusedCommand.ShouldUnfocus = false;
				_focusedCommand = null;
			}
			_resultNode.displayText = text2 ?? "OverworkedTerminal: No data was returned from your command.";
			TerminalNode resultNode = _resultNode;
			resultNode.displayText += "\n\n";
			_resultNode.clearPreviousText = true;
			__result = _resultNode;
			return false;
		}

		[HarmonyPatch("Start")]
		[HarmonyPostfix]
		private static void Start_Prefix(Terminal __instance)
		{
			_commands.Clear();
			SellingModule.Initialize(__instance);
			Scan.Initialize(__instance);
			LootFixCore.Initialize(__instance);
		}
	}
}
namespace Overworked.Core.Creatures.HoarderBug
{
	internal struct ExitData
	{
		public Vector3 current;

		public Vector3 opposite;

		public ExitData()
		{
			//IL_0006: 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)
			current = default(Vector3);
			opposite = default(Vector3);
		}
	}
	internal class OverriddenHoarderBug
	{
		protected HoarderBugAI currentAi;

		protected bool attachedToShip = false;

		protected bool canMove = true;

		protected Vector3 targetPosition;

		protected bool isMovingWithAgent = true;

		protected int joiningExitState = -1;

		protected ExitData currentExit;

		public OverriddenHoarderBug(HoarderBugAI enemyAi)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			targetPosition = ((Component)enemyAi).transform.position;
			currentAi = enemyAi;
			HoarderBugController.OverriddenBugs.Add(enemyAi, this);
			Start();
		}

		protected void MoveTo(Vector3 position)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			targetPosition = position;
		}

		protected ExitData GetNearestExit()
		{
			return new ExitData();
		}

		protected void GoInside()
		{
			joiningExitState = 0;
		}

		protected void GoOutside()
		{
			joiningExitState = 1;
		}

		public virtual void Start()
		{
		}

		public virtual void Update()
		{
		}

		public virtual void AiInterval()
		{
		}
	}
	[HarmonyPatch(typeof(HoarderBugAI))]
	internal class HoarderBugController
	{
		public static readonly ConditionalWeakTable<HoarderBugAI, OverriddenHoarderBug> OverriddenBugs = new ConditionalWeakTable<HoarderBugAI, OverriddenHoarderBug>();

		[HarmonyPatch("Update")]
		[HarmonyPrefix]
		private static bool CheckOverrideOnUpdate(HoarderBugAI __instance)
		{
			if (OverriddenBugs.TryGetValue(__instance, out var value))
			{
				value.Update();
				return false;
			}
			return true;
		}
	}
	internal class LootFixCore
	{
		internal class LootFixTheLootBug : OverriddenHoarderBug
		{
			public LootFixTheLootBug(HoarderBugAI enemyAi)
				: base(enemyAi)
			{
			}

			public override void Start()
			{
				base.Start();
			}

			public override void Update()
			{
				base.Update();
			}

			public override void AiInterval()
			{
				base.AiInterval();
			}
		}

		private static readonly string callMessage = "You have requested to call LootFix, our greatest asset™.\nMake sure only 3 employees are currently contracted.\n\nPlease CONFIRM or DENY";

		private static readonly Vector3 hangarShipOffset = new Vector3(0f, 0f, -7f);

		private static void SpawnLootFix()
		{
			//IL_0032: 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_0043: Unknown result type (might be due to invalid IL or missing references)
			EnemyType enemyType = StartOfRound.Instance.levels[1].Enemies[2].enemyType;
			NetworkObjectReference val = RoundManager.Instance.SpawnEnemyGameObject(GameObject.Find("Spawn1").transform.position, 0f, 1, enemyType);
			NetworkObject val2 = default(NetworkObject);
			if (((NetworkObjectReference)(ref val)).TryGet(ref val2, (NetworkManager)null))
			{
				new LootFixTheLootBug(((Component)val2).gameObject.GetComponent<HoarderBugAI>());
			}
		}

		public static void Initialize(Terminal t)
		{
			TerminalCommand callLootFix = new TerminalCommand("call");
			callLootFix.AddState("default", delegate(string[] args)
			{
				if (args.Length > 1 && OverworkedTerminal.Match(args[1], "lootfix"))
				{
					callLootFix.MoveTo("call");
					return callMessage;
				}
				callLootFix.Finish();
				return "No asset name to call.";
			});
			callLootFix.AddState("call", delegate(string[] args)
			{
				if (args.Length != 0)
				{
					if (OverworkedTerminal.Match(args[0], "confirm"))
					{
						t.PlayTerminalAudioServerRpc(2);
						callLootFix.Finish();
						SpawnLootFix();
						return "LootFix is now contracted in your team!";
					}
					if (OverworkedTerminal.Match(args[1], "deny"))
					{
						callLootFix.Finish();
						return "Procedure cancelled.";
					}
				}
				return callMessage;
			});
		}
	}
}