using System; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using GameNetcodeStuff; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("ShipComputerAssistant")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("ShipComputerAssistant")] [assembly: AssemblyTitle("ShipComputerAssistant")] [assembly: AssemblyVersion("1.0.0.0")] [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 ShipComputerAssistant { [HarmonyPatch(typeof(Terminal), "ParsePlayerSentence")] internal static class CrewStatusTerminalPatch { [HarmonyPrefix] private static bool BeforeParsePlayerSentence(Terminal __instance, ref TerminalNode __result) { if ((Object)(object)__instance == (Object)null) { return true; } string currentCommand = GetCurrentCommand(__instance); if (currentCommand.Equals("crew upgrade", StringComparison.OrdinalIgnoreCase) || currentCommand.Equals("crew monitoring", StringComparison.OrdinalIgnoreCase) || currentCommand.Equals("buy crew monitor", StringComparison.OrdinalIgnoreCase)) { __result = CreateCrewUpgradePurchaseNode(__instance); return false; } if (currentCommand.Equals("confirm", StringComparison.OrdinalIgnoreCase) && CrewUpgradeManager.PurchasePending) { __result = CompleteCrewUpgradePurchase(__instance); return false; } if (currentCommand.Equals("deny", StringComparison.OrdinalIgnoreCase) && CrewUpgradeManager.PurchasePending) { CrewUpgradeManager.PurchasePending = false; __result = CreateSimpleNode("\nPurchase cancelled.\n\n"); return false; } if (!currentCommand.Equals("crew", StringComparison.OrdinalIgnoreCase) && !currentCommand.Equals("status", StringComparison.OrdinalIgnoreCase)) { return true; } if (!CrewUpgradeManager.IsPurchased) { __result = CreateLockedCrewNode(); return false; } __result = CreateCrewStatusNode(); return false; } private static string GetCurrentCommand(Terminal terminal) { if ((Object)(object)terminal == (Object)null || (Object)(object)terminal.screenText == (Object)null) { return string.Empty; } string text = terminal.screenText.text ?? string.Empty; if (string.IsNullOrWhiteSpace(text)) { return string.Empty; } string[] array = text.Replace("\r", "").Split(new char[1] { '\n' }); for (int num = array.Length - 1; num >= 0; num--) { string text2 = array[num].Trim(); if (!string.IsNullOrWhiteSpace(text2)) { if (text2.StartsWith(">")) { return text2.Substring(1).Trim().ToLowerInvariant(); } return text2.ToLowerInvariant(); } } return string.Empty; } private static TerminalNode CreateSimpleNode(string text) { TerminalNode obj = ScriptableObject.CreateInstance(); obj.clearPreviousText = true; obj.displayText = text; return obj; } private static TerminalNode CreateLockedCrewNode() { return CreateSimpleNode("\n================================\n CREW MONITORING SOFTWARE\n================================\n\nACCESS DENIED\n\nCrew Monitoring Software is not installed.\n\nPrice: $" + 300 + "\n\nType \"crew upgrade\" to purchase.\n\n"); } private static TerminalNode CreateCrewUpgradePurchaseNode(Terminal terminal) { if (CrewUpgradeManager.IsPurchased) { CrewUpgradeManager.PurchasePending = false; return CreateSimpleNode("\nCrew Monitoring Software is already installed.\n\nType \"crew\" to access employee information.\n\n"); } if ((Object)(object)terminal == (Object)null) { CrewUpgradeManager.PurchasePending = false; return CreateSimpleNode("\nPurchase unavailable: terminal not found.\n\n"); } CrewUpgradeManager.PurchasePending = true; return CreateSimpleNode("\n================================\n CREW MONITORING SOFTWARE\n================================\n\nProvides remote access to employee:\n\n - Health\n - General location\n - Carried weight\n - Currently held equipment\n\nPrice: $" + 300 + "\nCurrent credits: $" + terminal.groupCredits + "\n\nPlease CONFIRM or DENY.\n\n"); } private static TerminalNode CompleteCrewUpgradePurchase(Terminal terminal) { CrewUpgradeManager.PurchasePending = false; if (CrewUpgradeManager.IsPurchased) { return CreateSimpleNode("\nCrew Monitoring Software is already installed.\n\n"); } if ((Object)(object)terminal == (Object)null) { return CreateSimpleNode("\nPurchase failed: terminal unavailable.\n\n"); } int num = 300; if (terminal.groupCredits < num) { return CreateSimpleNode("\nPURCHASE DECLINED\n\nInsufficient credits.\n\nRequired: $" + num + "\nAvailable: $" + terminal.groupCredits + "\n\n"); } terminal.groupCredits -= num; terminal.SyncGroupCreditsServerRpc(terminal.groupCredits, terminal.numberOfItemsInDropship); CrewUpgradeManager.IsPurchased = true; return CreateSimpleNode("\n================================\n PURCHASE COMPLETE\n================================\n\nCrew Monitoring Software installed.\n\nRemaining credits: $" + terminal.groupCredits + "\n\nType \"crew\" to access employee information.\n\n"); } private static TerminalNode CreateCrewStatusNode() { TerminalNode obj = ScriptableObject.CreateInstance(); obj.clearPreviousText = true; obj.displayText = BuildCrewStatusText(); return obj; } private static string BuildCrewStatusText() { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine(); stringBuilder.AppendLine("> CREW STATUS"); stringBuilder.AppendLine(); if ((Object)(object)StartOfRound.Instance == (Object)null || StartOfRound.Instance.allPlayerScripts == null) { stringBuilder.AppendLine("Crew information is currently unavailable."); stringBuilder.AppendLine(); return stringBuilder.ToString(); } PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts; int num = 0; int num2 = 0; PlayerControllerB[] array = allPlayerScripts; foreach (PlayerControllerB val in array) { if (!((Object)(object)val == (Object)null) && val.isPlayerControlled) { num++; string text = (string.IsNullOrWhiteSpace(val.playerUsername) ? "Unknown employee" : val.playerUsername); if (val.isPlayerDead) { stringBuilder.AppendLine(text + " : DECEASED"); continue; } num2++; stringBuilder.AppendLine(text + " : ALIVE"); stringBuilder.AppendLine(" Health: " + val.health); stringBuilder.AppendLine(" Weight: " + GetDisplayedWeight(val) + " lb"); stringBuilder.AppendLine(" Location: " + GetPlayerLocation(val)); stringBuilder.AppendLine(" Held item: " + GetHeldItemName(val)); stringBuilder.AppendLine(); } } if (num == 0) { stringBuilder.AppendLine("No active employees detected."); } else { stringBuilder.AppendLine("Employees alive: " + num2 + "/" + num); } stringBuilder.AppendLine(); return stringBuilder.ToString(); } private static int GetDisplayedWeight(PlayerControllerB player) { if ((Object)(object)player == (Object)null) { return 0; } return Mathf.RoundToInt(Mathf.Max(0f, player.carryWeight - 1f) * 105f); } private static string GetPlayerLocation(PlayerControllerB player) { if ((Object)(object)player == (Object)null) { return "Unknown"; } if (player.isInHangarShipRoom) { return "Ship"; } if (player.isInsideFactory) { return "Facility"; } return "Outside"; } private static string GetHeldItemName(PlayerControllerB player) { if ((Object)(object)player == (Object)null || (Object)(object)player.currentlyHeldObjectServer == (Object)null || (Object)(object)player.currentlyHeldObjectServer.itemProperties == (Object)null) { return "None"; } string itemName = player.currentlyHeldObjectServer.itemProperties.itemName; if (!string.IsNullOrWhiteSpace(itemName)) { return itemName; } return "Unknown item"; } } [HarmonyPatch(typeof(Terminal), "LoadNewNode")] internal static class CrewHelpPagePatch { [HarmonyPatch(typeof(Terminal), "LoadNewNode")] internal static class CrewUpgradeComingSoonPatch { private static string CrewUpgradeEntry => "\n>CREW UPGRADE // $" + 300 + "\nDisplays employee health, location, weight, and held equipment.\nType \"crew upgrade\" for purchase information.\n"; [HarmonyPrefix] private static void BeforeLoadNewNode(TerminalNode node) { if (!((Object)(object)node == (Object)null) && !string.IsNullOrEmpty(node.displayText) && IsShipUpgradesPage(node.displayText) && node.displayText.IndexOf(">CREW MONITORING SOFTWARE", StringComparison.OrdinalIgnoreCase) < 0) { node.displayText += CrewUpgradeEntry; } } private static bool IsShipUpgradesPage(string text) { return text.IndexOf("SHIP UPGRADES", StringComparison.OrdinalIgnoreCase) >= 0; } } private const string CrewHelpEntry = "\n>CREW\nDisplays employee status after Crew Monitoring Software is installed.\n\n>CREW UPGRADE\nViews or purchases Crew Monitoring Software.\n"; [HarmonyPrefix] private static void BeforeLoadNewNode(TerminalNode node) { if (!((Object)(object)node == (Object)null) && !string.IsNullOrEmpty(node.displayText) && IsHelpNode(node) && node.displayText.IndexOf(">CREW", StringComparison.OrdinalIgnoreCase) < 0) { node.displayText += "\n>CREW\nDisplays employee status after Crew Monitoring Software is installed.\n\n>CREW UPGRADE\nViews or purchases Crew Monitoring Software.\n"; } } private static bool IsHelpNode(TerminalNode node) { string displayText = node.displayText; if (displayText.IndexOf(">MOONS", StringComparison.OrdinalIgnoreCase) >= 0 && displayText.IndexOf(">STORE", StringComparison.OrdinalIgnoreCase) >= 0) { return displayText.IndexOf(">BESTIARY", StringComparison.OrdinalIgnoreCase) >= 0; } return false; } } internal static class CrewUpgradeManager { internal const int Price = 300; internal static bool IsPurchased; internal static bool PurchasePending; internal static void Reset() { IsPurchased = false; PurchasePending = false; } } [BepInPlugin("gavin.shipcomputerassistant", "Ship Computer Assistant", "1.0.0")] public class Plugin : BaseUnityPlugin { public const string GUID = "gavin.shipcomputerassistant"; public const string NAME = "Ship Computer Assistant"; public const string VERSION = "1.0.0"; private Harmony harmony; private void Awake() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown ((BaseUnityPlugin)this).Logger.LogInfo((object)"Applying Harmony patches..."); harmony = new Harmony("gavin.shipcomputerassistant"); harmony.PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Harmony patches applied."); } private void OnDestroy() { Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } } } }