Decompiled source of KroesTerminal v1.0.10

KroesTerminal.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using KroesTerminal.Patches;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("KroesTerminal")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("KroesTerminal")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("37420e05-2d4b-4fcd-a09f-844ba6ff45aa")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace KroesTerminal
{
	internal class ConfigControl
	{
		private ConfigEntry<bool> QuotaUICfg;

		private ConfigEntry<bool> QuotaNotifCfg;

		private ConfigEntry<bool> KScanCfg;

		private ConfigEntry<bool> KItemsCfg;

		private ConfigEntry<bool> KEnemyCfg;

		private ConfigEntry<bool> KEnemyPeacefulCfg;

		private ConfigEntry<bool> KPlayersCfg;

		private ConfigEntry<bool> InsideJokesCfg;

		internal bool enableQuotaUI
		{
			get
			{
				return QuotaUICfg.Value;
			}
			set
			{
				QuotaUICfg.Value = value;
			}
		}

		internal bool QuotaNotif
		{
			get
			{
				return QuotaNotifCfg.Value;
			}
			set
			{
				QuotaNotifCfg.Value = value;
			}
		}

		internal bool KScan
		{
			get
			{
				return KScanCfg.Value;
			}
			set
			{
				KScanCfg.Value = value;
			}
		}

		internal bool KItems
		{
			get
			{
				return KItemsCfg.Value;
			}
			set
			{
				KItemsCfg.Value = value;
			}
		}

		internal bool KEnemy
		{
			get
			{
				return KEnemyCfg.Value;
			}
			set
			{
				KEnemyCfg.Value = value;
			}
		}

		internal bool EnemyPeaceful
		{
			get
			{
				return KEnemyPeacefulCfg.Value;
			}
			set
			{
				KEnemyPeacefulCfg.Value = value;
			}
		}

		internal bool KPlayers
		{
			get
			{
				return KPlayersCfg.Value;
			}
			set
			{
				KPlayersCfg.Value = value;
			}
		}

		internal bool InsideJokes
		{
			get
			{
				return InsideJokesCfg.Value;
			}
			set
			{
				InsideJokesCfg.Value = value;
			}
		}

		public ConfigControl(ConfigFile config)
		{
			QuotaUICfg = config.Bind<bool>("Features", "Enable Quota UI", true, (ConfigDescription)null);
			QuotaNotifCfg = config.Bind<bool>("Features", "Enable Quota notification", true, (ConfigDescription)null);
			KScanCfg = config.Bind<bool>("Terminal Commands", "Allow KSCAN command", true, (ConfigDescription)null);
			KItemsCfg = config.Bind<bool>("Terminal Commands", "Allow KITEMS command", true, (ConfigDescription)null);
			KEnemyCfg = config.Bind<bool>("Terminal Commands", "Allow KENEMY command", true, (ConfigDescription)null);
			KEnemyPeacefulCfg = config.Bind<bool>("Terminal Commands", "List non-hostile enemies", true, (ConfigDescription)null);
			KPlayersCfg = config.Bind<bool>("Terminal Commands", "Allow KPLAYERS command", true, (ConfigDescription)null);
			InsideJokesCfg = config.Bind<bool>("Extra", "Enable Inside Jokes", false, "A part of the mod which enables inside jokes for my friends.");
		}
	}
	[BepInPlugin("com.kroes.kroesterminal", "KroesTerminal", "1.0.10")]
	public class KroesPlugin : BaseUnityPlugin
	{
		private const string GUID = "com.kroes.kroesterminal";

		private const string NAME = "KroesTerminal";

		private const string VERSION = "1.0.10";

		internal static ManualLogSource Log;

		internal static ConfigControl Configuration;

		private Harmony harmony = new Harmony("com.kroes.kroesterminal");

		private void Awake()
		{
			Log = ((BaseUnityPlugin)this).Logger;
			Configuration = new ConfigControl(((BaseUnityPlugin)this).Config);
			harmony.PatchAll(typeof(TerminalPatch));
			if (Configuration.enableQuotaUI || Configuration.QuotaNotif)
			{
				harmony.PatchAll(typeof(HUDManagerPatch));
			}
			if (Configuration.InsideJokes)
			{
				harmony.PatchAll(typeof(EnemyAIPatch));
			}
			Log.LogInfo((object)"Loaded succesfully!");
		}
	}
	internal class TextJumpAnimation : MonoBehaviour
	{
		private TextMeshProUGUI text;

		private float jumpTime;

		private const float jumpDuration = 0.2f;

		private const float jumpScale = 1.5f;

		private readonly Vector3 originalScale = new Vector3(1f, 1f, 1f);

		public void StartJump(TextMeshProUGUI target)
		{
			text = target;
			jumpTime = 0.2f;
		}

		private void Update()
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)text == (Object)null) && jumpTime > 0f)
			{
				float num = 1f - jumpTime / 0.2f;
				float num2 = Mathf.Sin(num * (float)Math.PI) * 0.5f + 1f;
				((TMP_Text)text).transform.localScale = originalScale * num2;
				jumpTime -= Time.deltaTime;
				if (jumpTime <= 0f)
				{
					((TMP_Text)text).transform.localScale = originalScale;
					Object.Destroy((Object)(object)this);
				}
			}
		}
	}
	internal class Utilities
	{
		public static TextMeshProUGUI QuotaText;

		public static GameObject ship;

		public static bool reachedQuota = false;

		public static int totalShipLoot;

		internal static readonly HashSet<string> nonHostileEnemies = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "docile locust bees", "manticoil", "tulip snake" };

		internal static TerminalNode CreateTerminalNode(string name)
		{
			TerminalNode val = ScriptableObject.CreateInstance<TerminalNode>();
			val.displayText = "[" + name + "]";
			val.terminalEvent = "";
			val.clearPreviousText = true;
			val.maxCharactersToType = 35;
			val.buyItemIndex = -1;
			val.buyVehicleIndex = -1;
			val.isConfirmationNode = false;
			val.buyRerouteToMoon = -1;
			val.displayPlanetInfo = -1;
			val.shipUnlockableID = -1;
			val.buyUnlockable = false;
			val.returnFromStorage = false;
			val.itemCost = 0;
			val.creatureFileID = -1;
			val.creatureName = "";
			val.storyLogFileID = -1;
			val.overrideOptions = false;
			val.acceptAnything = false;
			val.terminalOptions = Array.Empty<CompatibleNoun>();
			val.playSyncedClip = -1;
			val.loadImageSlowly = false;
			val.persistentImage = false;
			return val;
		}

		internal static void OnSubmitEnd(Terminal terminal)
		{
			terminal.screenText.ActivateInputField();
			((Selectable)terminal.screenText).Select();
		}

		internal static bool ShouldListItem(GrabbableObject item)
		{
			if (!item.itemProperties.isScrap)
			{
				return false;
			}
			StunGrenadeItem val = (StunGrenadeItem)(object)((item is StunGrenadeItem) ? item : null);
			if (val != null)
			{
				return !val.hasExploded;
			}
			return true;
		}

		internal static string KScanDisplayText()
		{
			string text = "";
			int num = 0;
			GrabbableObject[] source = Object.FindObjectsOfType<GrabbableObject>();
			GrabbableObject[] array = (from obj in source
				where ShouldListItem(obj) && !obj.isInShipRoom && !obj.isInElevator
				orderby obj.itemProperties.itemName
				select obj).ToArray();
			if (array.Length == 0)
			{
				return "\n\n\nNo objects were found.\n\n";
			}
			GrabbableObject[] array2 = array;
			foreach (GrabbableObject val in array2)
			{
				text += $"\n* {val.itemProperties.itemName} // ${val.scrapValue}";
				num += val.scrapValue;
			}
			return $"\n\n\nThere are {array.Length} objects outside the ship, totalling a value of ${num}.\n{text}\n\n";
		}

		internal static string KItemsDisplayText()
		{
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			int num4 = 0;
			int num5 = 0;
			int num6 = 0;
			int num7 = 0;
			int num8 = 0;
			GrabbableObject[] array = Object.FindObjectsOfType<GrabbableObject>();
			GrabbableObject[] array2 = array;
			foreach (GrabbableObject val in array2)
			{
				if (ShouldListItem(val))
				{
					if (val.isInShipRoom)
					{
						num3++;
						num4 += val.scrapValue;
					}
					else if (val.isHeld)
					{
						num7++;
						num8 += val.scrapValue;
					}
					else if (val.isInElevator)
					{
						num5++;
						num6 += val.scrapValue;
					}
					else
					{
						num++;
						num2 += val.scrapValue;
					}
				}
			}
			return $"\n\n\n[Items on moon] {num} : ${num2}\n[Items in ship] {num3} : ${num4}\n[Items being held] {num7} : ${num8}\n[Items on elevator/ship edge] {num5} : ${num6}\n\n";
		}

		private static bool ShouldListEnemy(EnemyAI enemy)
		{
			if (enemy.isEnemyDead)
			{
				return false;
			}
			if (!KroesPlugin.Configuration.EnemyPeaceful && nonHostileEnemies.Contains(enemy.enemyType.enemyName))
			{
				return false;
			}
			return true;
		}

		internal static string KEnemyDisplayText()
		{
			string text = "";
			string text2 = "";
			EnemyAI[] source = Object.FindObjectsOfType<EnemyAI>();
			EnemyAI[] array = (from enemy in source
				where !enemy.isOutside && ShouldListEnemy(enemy)
				orderby enemy.enemyType.enemyName
				select enemy).ToArray();
			EnemyAI[] array2 = (from enemy in source
				where enemy.isOutside && ShouldListEnemy(enemy)
				orderby enemy.enemyType.enemyName
				select enemy).ToArray();
			if (array.Length == 0 && array2.Length == 0)
			{
				return "\n\n\nNo enemies were found.\n\n";
			}
			EnemyAI[] array3 = array;
			foreach (EnemyAI val in array3)
			{
				string text3 = "???";
				DressGirlAI val2 = (DressGirlAI)(object)((val is DressGirlAI) ? val : null);
				text3 = ((val2 == null) ? val.enemyType.enemyPrefab.GetComponentInChildren<ScanNodeProperties>()?.headerText : ((Object)val2).name);
				text += $"\n* {text3} : {val.enemyHP}HP";
			}
			EnemyAI[] array4 = array2;
			foreach (EnemyAI val3 in array4)
			{
				string text4 = "???";
				DressGirlAI val4 = (DressGirlAI)(object)((val3 is DressGirlAI) ? val3 : null);
				text4 = ((val4 == null) ? val3.enemyType.enemyPrefab.GetComponentInChildren<ScanNodeProperties>()?.headerText : ((Object)val4).name);
				text2 += $"\n* {text4} : {val3.enemyHP}HP";
			}
			int num = array.Length + array2.Length;
			string text5 = $"\n\n\nThere are {num} enemies out there.\n";
			if (array.Length != 0)
			{
				text5 = text5 + "\n[Inside]" + text + "\n";
			}
			if (array2.Length != 0)
			{
				text5 = text5 + "\n[Outside]" + text2 + "\n";
			}
			return text5 + "\n";
		}

		internal static int calculateShipLootTotal()
		{
			List<GrabbableObject> source = (from obj in ship.GetComponentsInChildren<GrabbableObject>()
				where obj.itemProperties.isScrap && !(obj is RagdollGrabbableObject)
				select obj).ToList();
			return source.Sum((GrabbableObject scrap) => scrap.scrapValue);
		}

		public static void TriggerJump()
		{
			TextMeshProUGUI quotaText = QuotaText;
			if (!((Object)(object)quotaText == (Object)null))
			{
				TextJumpAnimation textJumpAnimation = ((Component)quotaText).gameObject.AddComponent<TextJumpAnimation>();
				textJumpAnimation.StartJump(quotaText);
			}
		}

		internal static string ConfigPermissionDisplayText(string command)
		{
			return "\n\n\n[" + command + "] is disabled in the mod config file.\n\n";
		}

		internal static string KroesDisplayText()
		{
			string text = "\n\n\nThanks for using KroesTerminal!\n\n";
			if (KroesPlugin.Configuration.KScan)
			{
				text += ">KSCAN\nTo see a detailed scan of all scrap.\n\n";
			}
			if (KroesPlugin.Configuration.KItems)
			{
				text += ">KITEMS\nTo see a count of all scrap.\n\n";
			}
			if (KroesPlugin.Configuration.KEnemy)
			{
				text += ">KENEMY\nTo see a scan of all enemies.\n\n";
			}
			if (KroesPlugin.Configuration.KPlayers)
			{
				text += ">KPLAYERS\nTo see a list of all player items.\n\n";
			}
			return text;
		}

		internal static string PlayersDisplayText()
		{
			PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
			PlayerControllerB[] array = allPlayerScripts.Where((PlayerControllerB player) => player.isPlayerControlled && !player.isPlayerDead).ToArray();
			int num = array.Length;
			string text = $"\n\n\nThere are {num} players alive:\n";
			PlayerControllerB[] array2 = array;
			foreach (PlayerControllerB val in array2)
			{
				text = text + "\n[" + val.playerUsername + "]\n";
				GrabbableObject[] itemSlots = val.ItemSlots;
				GrabbableObject[] array3 = itemSlots;
				foreach (GrabbableObject val2 in array3)
				{
					if ((Object)(object)val2 != (Object)null)
					{
						text = text + "- " + val2.itemProperties.itemName + "\n";
					}
				}
			}
			return text + "\n";
		}
	}
}
namespace KroesTerminal.Patches
{
	[HarmonyPatch(typeof(EnemyAI))]
	internal class EnemyAIPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch("Start")]
		private static void Postfix(EnemyAI __instance)
		{
			ScanNodeProperties componentInChildren = __instance.enemyType.enemyPrefab.GetComponentInChildren<ScanNodeProperties>();
			if (__instance is FlowermanAI)
			{
				componentInChildren.headerText = "Mammoet Mevrouw";
			}
			if (__instance is ClaySurgeonAI)
			{
				componentInChildren.headerText = "Fes de Barber";
			}
		}
	}
	[HarmonyPatch(typeof(HUDManager))]
	internal class HUDManagerPatch
	{
		[HarmonyPatch("Awake")]
		[HarmonyPostfix]
		private static void AwakePostfix(HUDManager __instance)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Expected O, but got Unknown
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: 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_0170: Unknown result type (might be due to invalid IL or missing references)
			if (KroesPlugin.Configuration.enableQuotaUI)
			{
				GameObject val = new GameObject("myHotbarUI");
				val.transform.SetParent(__instance.HUDContainer.transform, false);
				RectTransform val2 = val.AddComponent<RectTransform>();
				val2.anchorMin = new Vector2(0f, 1f);
				val2.anchorMax = new Vector2(0f, 1f);
				val2.pivot = new Vector2(0f, 1f);
				val2.anchoredPosition = new Vector2(60f, -10f);
				GameObject val3 = new GameObject("QuotaText");
				val3.transform.SetParent(val.transform, false);
				TextMeshProUGUI val4 = val3.AddComponent<TextMeshProUGUI>();
				RectTransform component = val3.GetComponent<RectTransform>();
				component.anchorMin = new Vector2(0.5f, 0.5f);
				component.anchorMax = new Vector2(0.5f, 0.5f);
				component.pivot = new Vector2(0.5f, 0.5f);
				component.anchoredPosition = new Vector2(50f, 20f);
				component.sizeDelta = new Vector2(300f, 50f);
				((TMP_Text)val4).font = ((TMP_Text)__instance.controlTipLines[0]).font;
				((TMP_Text)val4).fontSize = 20f;
				((TMP_Text)val4).fontStyle = (FontStyles)1;
				((TMP_Text)val4).text = "-placeholder-";
				((Graphic)val4).color = Color.white;
				((TMP_Text)val4).alignment = (TextAlignmentOptions)513;
				((TMP_Text)val4).enableWordWrapping = true;
				((TMP_Text)val4).overflowMode = (TextOverflowModes)0;
				Utilities.QuotaText = val4;
			}
			Utilities.ship = GameObject.Find("/Environment/HangarShip");
		}

		[HarmonyPatch("Update")]
		[HarmonyPostfix]
		private static void UpdatePostfix(HUDManager __instance)
		{
			int num = Utilities.calculateShipLootTotal();
			int profitQuota = TimeOfDay.Instance.profitQuota;
			if (KroesPlugin.Configuration.enableQuotaUI)
			{
				if (num != Utilities.totalShipLoot)
				{
					Utilities.totalShipLoot = num;
					Utilities.TriggerJump();
				}
				((TMP_Text)Utilities.QuotaText).text = $"[QUOTA] {Utilities.totalShipLoot} : {profitQuota}";
			}
			if (KroesPlugin.Configuration.QuotaNotif)
			{
				if (!Utilities.reachedQuota && num >= profitQuota)
				{
					Utilities.reachedQuota = true;
					KroesPlugin.Log.LogInfo((object)"sending quota notif...");
					__instance.globalNotificationAnimator.SetTrigger("TriggerNotif");
					((TMP_Text)__instance.globalNotificationText).text = "Quota has been reached!";
					__instance.UIAudio.PlayOneShot(__instance.globalNotificationSFX);
				}
				else if (Utilities.reachedQuota && num < profitQuota)
				{
					Utilities.reachedQuota = false;
				}
			}
		}
	}
	[HarmonyPatch(typeof(Terminal))]
	internal class TerminalPatch
	{
		[HarmonyPatch("OnSubmit")]
		[HarmonyPrefix]
		private static bool OnSubmitPrefix(Terminal __instance)
		{
			string text = __instance.screenText.text.Substring(__instance.screenText.text.Length - __instance.textAdded);
			switch (text.ToLower())
			{
			case "kscan":
			{
				KroesPlugin.Log.LogInfo((object)"Custom Command: kscan");
				TerminalNode val5 = Utilities.CreateTerminalNode("kscan");
				__instance.LoadNewNode(val5);
				return false;
			}
			case "kitems":
			{
				KroesPlugin.Log.LogInfo((object)"Custom Command: kitems");
				TerminalNode val4 = Utilities.CreateTerminalNode("kitems");
				__instance.LoadNewNode(val4);
				return false;
			}
			case "kenemy":
			{
				KroesPlugin.Log.LogInfo((object)"Custom Command: kenemy");
				TerminalNode val3 = Utilities.CreateTerminalNode("kenemy");
				__instance.LoadNewNode(val3);
				return false;
			}
			case "kroes":
			{
				KroesPlugin.Log.LogInfo((object)"Custom Command: kroes");
				TerminalNode val2 = Utilities.CreateTerminalNode("kroes");
				__instance.LoadNewNode(val2);
				return false;
			}
			case "kplayers":
			{
				KroesPlugin.Log.LogInfo((object)"Custom Command: kplayers");
				TerminalNode val = Utilities.CreateTerminalNode("kplayers");
				__instance.LoadNewNode(val);
				return false;
			}
			default:
				return true;
			}
		}

		[HarmonyPatch("TextPostProcess")]
		[HarmonyPrefix]
		private static bool TextPostProcessPrefix(ref string modifiedDisplayText, TerminalNode node, ref string __result, Terminal __instance)
		{
			string text = modifiedDisplayText.Trim();
			if (text.Contains("[kscan]"))
			{
				if (!KroesPlugin.Configuration.KScan)
				{
					KroesPlugin.Log.LogInfo((object)"[kscan] not permitted.");
					__result = Utilities.ConfigPermissionDisplayText("kscan");
					Utilities.OnSubmitEnd(__instance);
					return false;
				}
				KroesPlugin.Log.LogInfo((object)"Processing [kscan]...");
				__result = Utilities.KScanDisplayText();
				Utilities.OnSubmitEnd(__instance);
				return false;
			}
			if (text.Contains("[kitems]"))
			{
				if (!KroesPlugin.Configuration.KItems)
				{
					KroesPlugin.Log.LogInfo((object)"[kitems] not permitted.");
					__result = Utilities.ConfigPermissionDisplayText("kitems");
					Utilities.OnSubmitEnd(__instance);
					return false;
				}
				KroesPlugin.Log.LogInfo((object)"Processing [kitems]...");
				__result = Utilities.KItemsDisplayText();
				Utilities.OnSubmitEnd(__instance);
				return false;
			}
			if (text.Contains("[kenemy]"))
			{
				if (!KroesPlugin.Configuration.KEnemy)
				{
					KroesPlugin.Log.LogInfo((object)"[kenemy] not permitted.");
					__result = Utilities.ConfigPermissionDisplayText("kenemy");
					Utilities.OnSubmitEnd(__instance);
					return false;
				}
				KroesPlugin.Log.LogInfo((object)"Processing [kenemy]...");
				__result = Utilities.KEnemyDisplayText();
				Utilities.OnSubmitEnd(__instance);
				return false;
			}
			if (text.Contains("[kroes]"))
			{
				KroesPlugin.Log.LogInfo((object)"Processing [kroes]...");
				__result = Utilities.KroesDisplayText();
				Utilities.OnSubmitEnd(__instance);
				return false;
			}
			if (text.Contains("[kplayers]"))
			{
				if (!KroesPlugin.Configuration.KPlayers)
				{
					KroesPlugin.Log.LogInfo((object)"[kplayers] not permitted.");
					__result = Utilities.ConfigPermissionDisplayText("kplayers");
					Utilities.OnSubmitEnd(__instance);
					return false;
				}
				KroesPlugin.Log.LogInfo((object)"Processing [kplayers]...");
				__result = Utilities.PlayersDisplayText();
				Utilities.OnSubmitEnd(__instance);
				return false;
			}
			return true;
		}
	}
}