Decompiled source of Lethal Company Enhancer v0.1.12

Flowerful/Enhancer.dll

Decompiled 2 months ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
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(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("Enhancer")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Tweaks plugin for Lethal Company")]
[assembly: AssemblyFileVersion("0.1.12.0")]
[assembly: AssemblyInformationalVersion("0.1.12")]
[assembly: AssemblyProduct("Enhancer")]
[assembly: AssemblyTitle("Enhancer")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.12.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
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 Readme
{
	internal class DecompilerMessage
	{
		private const string Hello = "The source code for this project is freely available on request, btw. https://github.com/Crunchepillar/Lethal-Company-Enhancer/";

		internal DecompilerMessage()
		{
			if ("The source code for this project is freely available on request, btw. https://github.com/Crunchepillar/Lethal-Company-Enhancer/".Length != 69)
			{
			}
		}
	}
}
namespace Enhancer
{
	public class SPPatcher
	{
		[HarmonyPatch(typeof(TimeOfDay), "SetBuyingRateForDay")]
		[HarmonyPostfix]
		public static void BuyingRatePost(TimeOfDay __instance)
		{
			Plugin.Log.LogInfo((object)"TimeOfDay SetBuyingRateForDay");
			if (Plugin.Cfg.UseRandomPrices)
			{
				PriceRandomizer.Randomize();
			}
			if (StartOfRound.Instance.companyBuyingRate < Plugin.Cfg.MinimumBuyRate)
			{
				StartOfRound.Instance.companyBuyingRate = Plugin.Cfg.MinimumBuyRate;
			}
			StartOfRound.Instance.SyncCompanyBuyingRateServerRpc();
		}

		[HarmonyPatch(typeof(StartOfRound), "Start")]
		[HarmonyPrefix]
		public static bool StartOfRoundShipStartPre()
		{
			Plugin.Log.LogInfo((object)"StartOfRound Start");
			TimeOfDay.Instance.quotaVariables.deadlineDaysAmount = Plugin.Cfg.DaysPerQuota;
			return true;
		}

		[HarmonyPatch(typeof(TimeOfDay), "Start")]
		[HarmonyPostfix]
		public static void TimeOfDayOnStartPost(TimeOfDay __instance)
		{
			Plugin.Log.LogInfo((object)"TimeOfDay Start");
			__instance.globalTimeSpeedMultiplier = Plugin.Cfg.TimeScale;
		}

		[HarmonyPatch(typeof(HangarShipDoor), "Start")]
		[HarmonyPostfix]
		public static void HangarShipDoorPost(HangarShipDoor __instance)
		{
			Plugin.Log.LogInfo((object)"HangarShipDoor Start");
			__instance.doorPowerDuration = Plugin.Cfg.DoorTimer;
		}

		[HarmonyPatch(typeof(Terminal), "Update")]
		[HarmonyPostfix]
		public static void TerminalUpdatePost(Terminal __instance)
		{
			if (!((Component)__instance.terminalUIScreen).gameObject.activeSelf && Plugin.Cfg.KeepConsoleEnabled)
			{
				((Component)__instance.terminalUIScreen).gameObject.SetActive(true);
			}
		}

		[HarmonyPatch(typeof(Terminal), "LoadNewNode")]
		[HarmonyPostfix]
		public static void TerminalLoadHackPost(Terminal __instance, TerminalNode node)
		{
			if (!(((Object)node).name == "ScanInfo") || Plugin.Cfg.ThreatScannerType == 0 || !RoundManager.Instance.currentLevel.spawnEnemiesAndScrap)
			{
				return;
			}
			float currentEnemyPower = RoundManager.Instance.currentEnemyPower;
			int maxEnemyPowerCount = RoundManager.Instance.currentLevel.maxEnemyPowerCount;
			string text = "\nThreat Level: ";
			switch (Plugin.Cfg.ThreatScannerType)
			{
			case 1:
			{
				int numberOfEnemiesInScene = RoundManager.Instance.numberOfEnemiesInScene;
				text = "\nHostile Contacts: " + numberOfEnemiesInScene;
				break;
			}
			case 2:
				text = text + (currentEnemyPower / (float)maxEnemyPowerCount * 100f).ToString("N1") + "%";
				break;
			case 3:
			{
				string text2 = "CLEAR";
				float num = currentEnemyPower / (float)maxEnemyPowerCount;
				if (num > 0.99f)
				{
					text2 = "OMEGA";
				}
				else if (num > 0.69f)
				{
					text2 = "RED";
				}
				else if ((double)num > 0.49)
				{
					text2 = "ORANGE";
				}
				else if ((double)num > 0.24)
				{
					text2 = "YELLOW";
				}
				else if (num > 0f)
				{
					text2 = "GREEN";
				}
				text += text2;
				break;
			}
			}
			text += "\n";
			TMP_InputField screenText = __instance.screenText;
			screenText.text += text;
			__instance.currentText = __instance.screenText.text;
			__instance.textAdded = 0;
		}
	}
	[BepInPlugin("mom.llama.enhancer", "Enhancer", "0.1.12")]
	public class Plugin : BaseUnityPlugin
	{
		public static ManualLogSource Log;

		public static PluginConfig Cfg;

		private void Awake()
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			Cfg = new PluginConfig(this);
			if (!Cfg.Enabled)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Globally disabled, exit");
				return;
			}
			Harmony val = new Harmony("Enhancer");
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Enabled, patching now");
			val.PatchAll(typeof(SPPatcher));
			if (Cfg.DoSuitPatches)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Doing suit patches");
				val.PatchAll(typeof(SuitPatches));
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Doing protection patches");
			val.PatchAll(typeof(SPProtectionPatches));
		}
	}
	public class PluginConfig
	{
		public readonly bool Enabled;

		public readonly bool KeepConsoleEnabled;

		public readonly bool UseRandomPrices;

		public readonly bool DoSuitPatches;

		public readonly float TimeScale;

		public readonly float MinimumBuyRate;

		public readonly float DoorTimer;

		public readonly int DaysPerQuota;

		public readonly int ThreatScannerType;

		public readonly SPProtectionPatches.ProtectionType ScrapProtection;

		public PluginConfig(Plugin BindingPlugin)
		{
			Enabled = ((BaseUnityPlugin)BindingPlugin).Config.Bind<bool>("Enhancer", "bEnabled", true, "Globally enable/disable the plugin").Value;
			KeepConsoleEnabled = ((BaseUnityPlugin)BindingPlugin).Config.Bind<bool>("Enhancer", "bAlwaysShowTerminal", true, "Whether to keep the terminal enabled after a player stops using it\nHost Required: No").Value;
			UseRandomPrices = ((BaseUnityPlugin)BindingPlugin).Config.Bind<bool>("Enhancer", "bUseRandomPrices", false, "Enables the random prices setting. Great if you're using longer quota deadlines.\nThis uses a variety of things to randomize prices such as the company mood, time passed in the quota, etc.\nRespects the minimum sale value, too.\nHost Required: Yes").Value;
			DoSuitPatches = ((BaseUnityPlugin)BindingPlugin).Config.Bind<bool>("Enhancer", "bUnlockSuits", false, "Unlocks a few of the cheaper suits from the start so your crew has options.\nHost Required: Yes").Value;
			TimeScale = ((BaseUnityPlugin)BindingPlugin).Config.Bind<float>("Enhancer", "fTimeScale", 1.5f, "How fast time passes on moons. Lower values mean time passes more slowly.\nRecommended value for single play: 1.15\nHost Required: Yes").Value;
			MinimumBuyRate = ((BaseUnityPlugin)BindingPlugin).Config.Bind<float>("Enhancer", "fMinCompanyBuyPCT", 0f, "The default formula for selling items to the company doesn't allow days remaining above 3.\nAlways keep this set to at least 0.0 but you probably want something higher if you have more days set for the quota.\nRecommended values for games above 3 days: 0.3 - 0.5\nHost Required: Yes").Value;
			DoorTimer = ((BaseUnityPlugin)BindingPlugin).Config.Bind<float>("Enhancer", "fDoorTimer", 30f, "How long the hangar door can be kept shut at a time (in seconds)\nRecommended values: 60.0 - 180.0\nHost Required: All players should use the same setting here").Value;
			DaysPerQuota = ((BaseUnityPlugin)BindingPlugin).Config.Bind<int>("Enhancer", "iQuotaDays", 3, "How long you have to meet each quota (in days)\nRecommended values: 3 - 7\nHost Required: Yes").Value;
			ThreatScannerType = ((BaseUnityPlugin)BindingPlugin).Config.Bind<int>("Enhancer", "eThreatScannerType", 0, "How the threat scanner functions. Valid types:\n0 - Disabled\n1 - Number of Enemies on level\n2 - Percentage of max enemies on level\n3 - Vague Text description (In order of threat level) [Clear -> Green -> Yellow -> Orange - Red]\nHost Required: No").Value;
			ScrapProtection = ((BaseUnityPlugin)BindingPlugin).Config.Bind<SPProtectionPatches.ProtectionType>("Enhancer", "eScrapProtection", SPProtectionPatches.ProtectionType.SAVE_NONE, "Sets how scrap will be handled when all players die in a round.\nSAVE_NONE: Default all scrap is deleted\nSAVE_ALL: No scrap is removed\nSAVE_COINFLIP: Each piece of scrap has a 50/50 of being removed\nHost Required: Yes").Value;
		}
	}
	public static class PriceRandomizer
	{
		public static void Randomize()
		{
			Plugin.Log.LogInfo((object)"Randomizing Prices");
			if (TimeOfDay.Instance.daysUntilDeadline < 1)
			{
				StartOfRound.Instance.companyBuyingRate = 1f;
				return;
			}
			float moodFactor = GetMoodFactor();
			Plugin.Log.LogInfo((object)"Got mood factor");
			float num = (float)(1.0 + (double)(0.05f * (float)(Plugin.Cfg.DaysPerQuota - TimeOfDay.Instance.daysUntilDeadline)));
			num = Mathf.Clamp(num, 1f, 2f);
			Random random = new Random(StartOfRound.Instance.randomMapSeed + 77);
			float companyBuyingRate = (float)random.NextDouble() * (1f - moodFactor * num) + moodFactor;
			Plugin.Log.LogInfo((object)("New prices set at" + companyBuyingRate));
			Plugin.Log.LogInfo((object)("    factors " + moodFactor + " : " + num + " : " + (StartOfRound.Instance.randomMapSeed + 77)));
			StartOfRound.Instance.companyBuyingRate = companyBuyingRate;
		}

		private static bool IsCompanyAvailable()
		{
			if (TimeOfDay.Instance == null)
			{
				return false;
			}
			if (TimeOfDay.Instance.currentCompanyMood == null)
			{
				return false;
			}
			if (((Object)TimeOfDay.Instance.currentCompanyMood).name == null)
			{
				return false;
			}
			return true;
		}

		private static float GetMoodFactor()
		{
			Plugin.Log.LogInfo((object)"Get mood factor");
			float num = 0.4f;
			if (!IsCompanyAvailable())
			{
				return num;
			}
			string name = ((Object)TimeOfDay.Instance.currentCompanyMood).name;
			if (1 == 0)
			{
			}
			float result = name switch
			{
				"SilentCalm" => 0.35f, 
				"SnoringGiant" => 0.45f, 
				"Agitated" => 0.25f, 
				_ => num, 
			};
			if (1 == 0)
			{
			}
			return result;
		}
	}
	public class SPProtectionPatches
	{
		public enum ProtectionType
		{
			SAVE_NONE,
			SAVE_ALL,
			SAVE_COINFLIP
		}

		private static Random rng;

		[HarmonyPatch(typeof(RoundManager), "DespawnPropsAtEndOfRound")]
		[HarmonyPrefix]
		public static bool ProtectionPrefix(RoundManager __instance, bool despawnAllItems)
		{
			if (Plugin.Cfg.ScrapProtection == ProtectionType.SAVE_NONE || despawnAllItems)
			{
				return true;
			}
			if (((NetworkBehaviour)__instance).IsHost || ((NetworkBehaviour)__instance).IsServer)
			{
				Plugin.Log.LogInfo((object)("ProtectionPatch -> " + despawnAllItems + " : " + StartOfRound.Instance.allPlayersDead));
				if (StartOfRound.Instance.allPlayersDead)
				{
					GrabbableObject[] array = Object.FindObjectsOfType<GrabbableObject>();
					rng = new Random(StartOfRound.Instance.randomMapSeed + 83);
					GrabbableObject[] array2 = array;
					foreach (GrabbableObject val in array2)
					{
						ProtectionType scrapProtection = Plugin.Cfg.ScrapProtection;
						if (val.isInShipRoom)
						{
							if (!val.itemProperties.isScrap || ShouldSaveScrap(scrapProtection))
							{
								Plugin.Log.LogInfo((object)("Preserving ship item: " + ((Object)val).name));
							}
							else
							{
								DeleteItem(val);
							}
						}
						else
						{
							DeleteItem(val);
						}
					}
					GameObject[] array3 = GameObject.FindGameObjectsWithTag("TemporaryEffect");
					for (int j = 0; j < array3.Length; j++)
					{
						Object.Destroy((Object)(object)array3[j]);
					}
					return false;
				}
			}
			return true;
			void DeleteItem(GrabbableObject item)
			{
				Plugin.Log.LogInfo((object)("Despawning item: " + ((Object)item).name + " in ship: " + item.isInShipRoom));
				((Component)item).gameObject.GetComponent<NetworkObject>().Despawn(true);
				if (__instance.spawnedSyncedObjects.Contains(((Component)item).gameObject))
				{
					__instance.spawnedSyncedObjects.Remove(((Component)item).gameObject);
				}
			}
		}

		public static bool ShouldSaveScrap(ProtectionType pType)
		{
			return pType switch
			{
				ProtectionType.SAVE_ALL => true, 
				ProtectionType.SAVE_COINFLIP => rng.NextDouble() > 0.49, 
				_ => false, 
			};
		}
	}
	public class SuitPatches
	{
		private static readonly MethodInfo unlockItem = typeof(StartOfRound).GetMethod("SpawnUnlockable", BindingFlags.Instance | BindingFlags.NonPublic);

		public static void SpawnUnlockableDelegate(StartOfRound instance, int ID)
		{
			unlockItem.Invoke(instance, new object[1] { ID });
		}

		[HarmonyPatch(typeof(StartOfRound), "Start")]
		[HarmonyPostfix]
		public static void StartOfRoundSuitPatch(StartOfRound __instance)
		{
			Plugin.Log.LogInfo((object)"Setting unlocked suits this round");
			SpawnUnlockableDelegate(__instance, 1);
			SpawnUnlockableDelegate(__instance, 2);
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "Enhancer";

		public const string PLUGIN_NAME = "Enhancer";

		public const string PLUGIN_VERSION = "0.1.12";
	}
}