Decompiled source of InfernaleMod v0.4.0

BepInEx/plugins/InfernaleMod.dll

Decompiled 10 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 GameNetcodeStuff;
using HarmonyLib;
using InfernaleMod.Patches;
using Microsoft.CodeAnalysis;
using TMPro;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.InputSystem;
using UnityEngine.SceneManagement;
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: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("InfernaleMod")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Multi purpose Mod for Lethal Company")]
[assembly: AssemblyFileVersion("0.4.0.0")]
[assembly: AssemblyInformationalVersion("0.4.0")]
[assembly: AssemblyProduct("InfernaleMod")]
[assembly: AssemblyTitle("InfernaleMod")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.4.0.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 InfernaleMod
{
	public class InfernaleModConfig
	{
		public static ConfigEntry<bool> ClockFormat;

		public static ConfigEntry<bool> WeightUnit;

		public static ConfigEntry<bool> ClockInShip;

		public static ConfigEntry<bool> ShowHp;

		public static ConfigEntry<int> ItemStorage;

		public static ConfigEntry<bool> NoSellLimit;

		public static ConfigEntry<bool> ShipLoot;

		public static ConfigEntry<bool> SkipToMultiplayerMenu;

		public static ConfigEntry<bool> TerminalWalkie;

		public static ConfigEntry<bool> ClockVisibleInShip;

		public static ConfigEntry<bool> InfiniteSprintAtCompanyBuilding;

		public static ConfigEntry<bool> FadeOutChat;

		public static ConfigEntry<bool> ReOpenLobby;

		public static ConfigEntry<bool> QuickDrop;

		public static ConfigEntry<bool> InvertHotbarScrollDirection;

		public static ConfigEntry<bool> RestartLobby;

		public static ConfigEntry<bool> ForceRestart;

		public static void Init(ConfigFile config)
		{
			ItemStorage = config.Bind<int>("General", "ItemStorage", 45, "Sets the maximum amount of Items you can save in your ship.");
			NoSellLimit = config.Bind<bool>("General", "NoSellLimit", false, "If set to true the item limit on the deposit desk at the company building will be removed.");
			ShipLoot = config.Bind<bool>("General", "ShipLoot", false, "Set to true to enable the display to show all your scrap value on ship.");
			SkipToMultiplayerMenu = config.Bind<bool>("Miscellaneous", "ForceOnlineMode", false, "If set to true the game will skip the Online/LAN screen on startup forcing into Online mode.");
			ReOpenLobby = config.Bind<bool>("Miscellaneous", "ReOpenLobby", false, "If set to true the lobby will be joinable between the rounds while the ship is in the orbit. Also the invite buttom will work if set to true.");
			RestartLobby = config.Bind<bool>("Miscellaneous", "RestartLobby", false, "If set to true the lobby can be restarted by typing /restart into the chat (only the Host).");
			ForceRestart = config.Bind<bool>("Miscellaneous", "ForceRestart", false, "If set to true the confirmation step when restarting will be skipped.");
			ClockFormat = config.Bind<bool>("HUD", "ClockFormat", false, "If set to true changes the ingame clock to appear in the 24h format instead of AM/PM.");
			WeightUnit = config.Bind<bool>("HUD", "WeightUnit", false, "If set to true changes the weight unit to appear and calculated in kg instead of lb.");
			FadeOutChat = config.Bind<bool>("HUD", "FadeOutChat", false, "If set to true the chat window will be hidden after a short period of time and will only be visible if there is a new message or you open the chat.");
			ShowHp = config.Bind<bool>("HUD", "ShowHp", false, "If set to true in the top left will be shown your current HP as a number.");
			ClockVisibleInShip = config.Bind<bool>("HUD", "ClockVisibleInShip", false, "If set to true changes the ingame clock to also appear inside the ship while on a mission.");
			TerminalWalkie = config.Bind<bool>("QOL", "TerminalWalkie", false, "If set to true you will be able to use the walkie-talkie on the terminal without pressing any key. The walkie-talkie needs to be activated before.");
			InfiniteSprintAtCompanyBuilding = config.Bind<bool>("QOL", "InfiniteSprintAtCompanyBuilding", false, "If set to true there will be no stamina drain while landed at the company building.");
			QuickDrop = config.Bind<bool>("QOL", "QuickDrop", false, "If set to true you will be able to fast drop your items by spamming the drop button (G)");
			InvertHotbarScrollDirection = config.Bind<bool>("QOL", "InvertHotbarScrollDirection", false, "If set to true the scroll direction of the hotbar will be fixed.");
		}
	}
	public class InfernaleModConfigLog
	{
		public static void LogConfigSettings()
		{
			int value = InfernaleModConfig.ItemStorage.Value;
			bool value2 = InfernaleModConfig.SkipToMultiplayerMenu.Value;
			bool value3 = InfernaleModConfig.ClockFormat.Value;
			bool value4 = InfernaleModConfig.WeightUnit.Value;
			bool value5 = InfernaleModConfig.ShipLoot.Value;
			bool value6 = InfernaleModConfig.NoSellLimit.Value;
			bool value7 = InfernaleModConfig.TerminalWalkie.Value;
			bool value8 = InfernaleModConfig.InfiniteSprintAtCompanyBuilding.Value;
			bool value9 = InfernaleModConfig.FadeOutChat.Value;
			bool value10 = InfernaleModConfig.ReOpenLobby.Value;
			bool value11 = InfernaleModConfig.ShowHp.Value;
			bool value12 = InfernaleModConfig.QuickDrop.Value;
			bool value13 = InfernaleModConfig.InvertHotbarScrollDirection.Value;
			bool value14 = InfernaleModConfig.RestartLobby.Value;
			bool value15 = InfernaleModConfig.ForceRestart.Value;
			if (value2)
			{
				InfernaleMod.Log.LogInfo((object)"Patch applied: The game will be forced into Online-mode.");
			}
			if (value10)
			{
				InfernaleMod.Log.LogInfo((object)"Patch applied: Your lobbies will be joinable between each mission.");
			}
			if (value3)
			{
				InfernaleMod.Log.LogInfo((object)"Patch applied: The ingame clock will now be shown in the 24h format.");
			}
			if (value > 45 || value < 45)
			{
				InfernaleMod.Log.LogInfo((object)("Patch applied: The custom item storage has been set to " + value + "."));
			}
			if (value4)
			{
				InfernaleMod.Log.LogInfo((object)"Patch applied: The weight unit will now be shown and calculated as kg.");
			}
			if (value5)
			{
				InfernaleMod.Log.LogInfo((object)"Patch applied: The ship loot counter has been enabled.");
			}
			if (value7)
			{
				InfernaleMod.Log.LogInfo((object)"Patch applied: The walkie-talkie will now be used, if activated, when entering the terminal.");
			}
			if (value6)
			{
				InfernaleMod.Log.LogInfo((object)"Patch applied: The item limit on the deposit desk at the company building has been removed.");
			}
			if (value8)
			{
				InfernaleMod.Log.LogInfo((object)"Patch applied: Infite stamina at the company building has been enabled.");
			}
			if (value9)
			{
				InfernaleMod.Log.LogInfo((object)"Patch applied: The chat window will be hidden until there are new messages.");
			}
			if (value11)
			{
				InfernaleMod.Log.LogInfo((object)"Patch applied: Your current HP will be shown as a number.");
			}
			if (value12)
			{
				InfernaleMod.Log.LogInfo((object)"Patch applied: You are now able to quick drop items.");
			}
			if (value13)
			{
				InfernaleMod.Log.LogInfo((object)"Patch applied: The scroll direction of the hotbar will now be inverted.");
			}
			if (value14)
			{
				InfernaleMod.Log.LogInfo((object)"Patch applied: The lobby can be restarted by chat commands.");
			}
			if (value14 && value15)
			{
				InfernaleMod.Log.LogInfo((object)"Patch applied: The lobby will be force restarted when typing /restart.");
			}
		}
	}
	[BepInPlugin("InfernaleMod", "InfernaleMod", "0.4.0")]
	public class InfernaleMod : BaseUnityPlugin
	{
		private readonly Harmony harmony = new Harmony("InfernaleMod");

		private static InfernaleMod Instance;

		internal static ManualLogSource Log;

		private void Awake()
		{
			if ((Object)(object)Instance == (Object)null)
			{
				Instance = this;
			}
			Log = ((BaseUnityPlugin)this).Logger;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin InfernaleMod 0.4.0 is loaded!");
			InfernaleModConfig.Init(((BaseUnityPlugin)this).Config);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Config file has been created or updated!");
			InfernaleModConfigLog.LogConfigSettings();
			harmony.PatchAll(typeof(InfernaleMod));
			harmony.PatchAll(typeof(ForceOnlineMode_Patch));
			harmony.PatchAll(typeof(ReOpenLobby));
			harmony.PatchAll(typeof(RestartLobby_Patch));
			harmony.PatchAll(typeof(ItemStorage_Patch));
			harmony.PatchAll(typeof(ShipLoot_Patch));
			harmony.PatchAll(typeof(NoSellLimit_Patch));
			harmony.PatchAll(typeof(ClockFormat_Patch));
			harmony.PatchAll(typeof(WeightUnit_Patch));
			harmony.PatchAll(typeof(ClockVisibleInShip_Patch));
			harmony.PatchAll(typeof(FadeOutChat_Patch));
			harmony.PatchAll(typeof(ShopHp_Patch));
			harmony.PatchAll(typeof(TerminalWalkie_Patch));
			harmony.PatchAll(typeof(InfiniteSprintAtCompanyBuilding_Patch));
			harmony.PatchAll(typeof(QuickDrop_Patch));
			harmony.PatchAll(typeof(InvertHotbarScroll_Patch));
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "InfernaleMod";

		public const string PLUGIN_NAME = "InfernaleMod";

		public const string PLUGIN_VERSION = "0.4.0";
	}
}
namespace InfernaleMod.Patches
{
	[HarmonyPatch(typeof(HUDManager))]
	public class ClockFormat_Patch
	{
		[HarmonyPatch("SetClock")]
		[HarmonyPrefix]
		public static bool ClockFormat(HUDManager __instance, ref string __result, float timeNormalized, float numberOfHours, bool createNewLine = true)
		{
			bool value = InfernaleModConfig.ClockFormat.Value;
			int num = (int)(timeNormalized * (60f * numberOfHours)) + 360;
			int num2 = (int)Mathf.Floor((float)(num / 60));
			num2 %= 24;
			int num3 = num % 60;
			string text;
			if (value)
			{
				text = $"{num2:00}:{num3:00}";
			}
			else if (num2 >= 24)
			{
				text = "12:00\nAM";
			}
			else
			{
				string text2 = (createNewLine ? "\n" : " ");
				string text3 = ((num2 < 12) ? "AM" : "PM");
				if (num2 > 12)
				{
					num2 %= 12;
				}
				int num4 = num % 60;
				text = $"{num2:00}:{num4:00}".TrimStart('0') + text2 + text3;
			}
			((TMP_Text)__instance.clockNumber).text = text;
			__result = text;
			return false;
		}
	}
	[HarmonyPatch(typeof(HUDManager))]
	public class ClockVisibleInShip_Patch
	{
		[HarmonyPatch("SetClockVisible")]
		[HarmonyPostfix]
		public static void ClockVisibleInShip(HUDManager __instance)
		{
			if (InfernaleModConfig.ClockVisibleInShip.Value && GameNetworkManager.Instance.localPlayerController.isInHangarShipRoom && !GameNetworkManager.Instance.localPlayerController.inTerminalMenu)
			{
				__instance.Clock.targetAlpha = 1f;
			}
		}
	}
	[HarmonyPatch(typeof(HUDManager))]
	public class FadeOutChat_Patch
	{
		[HarmonyPatch("OpenMenu_performed")]
		[HarmonyPatch("SubmitChat_performed")]
		[HarmonyPatch("AddChatMessage")]
		[HarmonyPostfix]
		public static void HidingChat(ref HUDManager __instance)
		{
			if (InfernaleModConfig.FadeOutChat.Value)
			{
				__instance.PingHUDElement(__instance.Chat, 5f, 1f, 0f);
			}
		}
	}
	[HarmonyPatch]
	public class ForceOnlineMode_Patch
	{
		private static bool skippedPreInitScene;

		private static bool skippedInitScene;

		[HarmonyPatch(typeof(PreInitSceneScript), "Awake")]
		[HarmonyPrefix]
		public static bool InitializeGameManager()
		{
			if (InfernaleModConfig.SkipToMultiplayerMenu.Value && !skippedPreInitScene)
			{
				skippedPreInitScene = true;
				InfernaleMod.Log.LogInfo((object)"Loading the GameManager while inside InitScene...");
				SceneManager.LoadScene("InitScene");
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(InitializeGame), "Start")]
		[HarmonyPrefix]
		public static bool LoadMultiplayerMenuScene()
		{
			if (InfernaleModConfig.SkipToMultiplayerMenu.Value && !skippedInitScene)
			{
				skippedInitScene = true;
				InfernaleMod.Log.LogInfo((object)"Skipping to MainMenu...");
				SceneManager.LoadScene("MainMenu");
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(PlayerControllerB))]
	public class InfiniteSprintAtCompanyBuilding_Patch
	{
		[HarmonyPostfix]
		[HarmonyPatch("Update")]
		private static void InfiniteStaminaAtCompanyPatch(PlayerControllerB __instance, ref float ___sprintMeter)
		{
			if (InfernaleModConfig.InfiniteSprintAtCompanyBuilding.Value)
			{
				SelectableLevel val = StartOfRound.Instance?.currentLevel;
				if ((Object)(object)val != (Object)null && val.levelID == 3)
				{
					___sprintMeter = 1f;
				}
			}
		}
	}
	public static class InvertHotbarScroll_Patch
	{
		[HarmonyPatch(typeof(PlayerControllerB), "ScrollMouse_performed")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> InvertHotbarScrollDirection(IEnumerable<CodeInstruction> instructions)
		{
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			if (InfernaleModConfig.InvertHotbarScrollDirection.Value)
			{
				for (int i = 1; i < list.Count; i++)
				{
					if (list[i].opcode == OpCodes.Ble_Un && list[i - 1].opcode == OpCodes.Ldc_R4 && (float)list[i - 1].operand == 0f)
					{
						list[i].opcode = OpCodes.Bge_Un;
						break;
					}
				}
			}
			return list.AsEnumerable();
		}
	}
	[HarmonyPatch(typeof(StartOfRound))]
	public class ItemStorage_Patch
	{
		[HarmonyPatch("Awake")]
		[HarmonyPostfix]
		public static void ShipItemStorage(ref int ___maxShipItemCapacity)
		{
			int value = InfernaleModConfig.ItemStorage.Value;
			if (value > 45 || value < 45)
			{
				___maxShipItemCapacity = value;
			}
			else
			{
				___maxShipItemCapacity = 45;
			}
		}
	}
	[HarmonyPatch(typeof(DepositItemsDesk))]
	public class NoSellLimit_Patch
	{
		[HarmonyPatch("PlaceItemOnCounter")]
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			if (InfernaleModConfig.NoSellLimit.Value)
			{
				FieldInfo fieldInfo = AccessTools.Field(typeof(DepositItemsDesk), "deskObjectsContainer");
				bool flag = false;
				int num = -1;
				int num2 = -1;
				List<CodeInstruction> list = new List<CodeInstruction>(instructions);
				for (int i = 0; i < list.Count; i++)
				{
					CodeInstruction val = list[i];
					if (!flag && val.opcode == OpCodes.Ldfld && (FieldInfo)val.operand == fieldInfo)
					{
						flag = true;
						num = i - 1;
					}
					else if (flag && val.opcode == OpCodes.Bge)
					{
						num2 = i;
						break;
					}
				}
				if (num > -1 && num2 > -1)
				{
					list[num].opcode = OpCodes.Nop;
					list.RemoveRange(num, num2 - num + 1);
				}
				return list.AsEnumerable();
			}
			return instructions;
		}
	}
	[HarmonyPatch(typeof(PlayerControllerB))]
	internal class QuickDrop_Patch
	{
		[HarmonyPatch("Discard_performed")]
		[HarmonyPrefix]
		private static void QuickDrop(PlayerControllerB __instance, ref bool ___isHoldingObject, ref GrabbableObject[] ___ItemSlots)
		{
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Expected O, but got Unknown
			if (!InfernaleModConfig.QuickDrop.Value || ___isHoldingObject)
			{
				return;
			}
			MethodInfo method = typeof(PlayerControllerB).GetMethod("NextItemSlot", BindingFlags.Instance | BindingFlags.NonPublic);
			MethodInfo method2 = typeof(PlayerControllerB).GetMethod("SwitchToItemSlot", BindingFlags.Instance | BindingFlags.NonPublic);
			if (!(method != null) || !(method2 != null))
			{
				return;
			}
			int currentItemSlot = __instance.currentItemSlot;
			object[] parameters = new object[1] { true };
			for (int num = (int)method.Invoke(__instance, parameters); num != currentItemSlot; num = (num + 1) % ___ItemSlots.Length)
			{
				if ((Object)___ItemSlots[num] != (Object)null)
				{
					method2.Invoke(__instance, new object[2] { num, null });
					break;
				}
			}
		}
	}
	[HarmonyPatch]
	internal class ReOpenLobby
	{
		private static QuickMenuManager _quickMenuManager;

		[HarmonyPostfix]
		[HarmonyPatch(typeof(GameNetworkManager), "Singleton_OnClientConnectedCallback")]
		private static void LogConnect()
		{
			InfernaleMod.Log.LogDebug((object)"A Player has connected to the lobby.");
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(GameNetworkManager), "Singleton_OnClientDisconnectCallback")]
		private static void LogDisconnect()
		{
			InfernaleMod.Log.LogDebug((object)"A Player has disconnected from the lobby.");
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(GameNetworkManager), "ConnectionApproval")]
		private static void FixConnectionApproval(GameNetworkManager __instance, ConnectionApprovalResponse response)
		{
			if (!response.Approved && !(response.Reason != "The Game has already started!") && __instance.gameHasStarted && StartOfRound.Instance.inShipPhase)
			{
				InfernaleMod.Log.LogDebug((object)"Approving incoming late connection.");
				response.Reason = "";
				response.Approved = true;
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(QuickMenuManager), "InviteFriendsButton")]
		private static void FixFriendInviteButton()
		{
			if (GameNetworkManager.Instance.gameHasStarted && StartOfRound.Instance.inShipPhase)
			{
				GameNetworkManager.Instance.InviteFriendsUI();
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(GameNetworkManager), "LeaveLobbyAtGameStart")]
		private static bool PreventSteamLobbyLeaving(GameNetworkManager __instance)
		{
			InfernaleMod.Log.LogDebug((object)"Preventing the closing of the Steam lobby.");
			return false;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(StartOfRound), "StartGame")]
		private static void CloseSteamLobby(StartOfRound __instance)
		{
			if (((NetworkBehaviour)__instance).IsServer && __instance.inShipPhase)
			{
				InfernaleMod.Log.LogDebug((object)"Setting lobby to not joinable.");
				GameNetworkManager.Instance.SetLobbyJoinable(false);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(StartOfRound), "EndOfGame")]
		private static IEnumerator ReopenSteamLobby(IEnumerator coroutine, StartOfRound __instance)
		{
			while (coroutine.MoveNext())
			{
				yield return coroutine.Current;
			}
			if (!((NetworkBehaviour)__instance).IsServer)
			{
				yield break;
			}
			yield return (object)new WaitForSeconds(0.5f);
			yield return (object)new WaitUntil((Func<bool>)(() => !__instance.firingPlayersCutsceneRunning));
			InfernaleMod.Log.LogDebug((object)"Reopening lobby, setting it to joinable.");
			GameNetworkManager manager = GameNetworkManager.Instance;
			if (manager.currentLobby.HasValue)
			{
				manager.SetLobbyJoinable(true);
				if ((Object)(object)_quickMenuManager == (Object)null)
				{
					_quickMenuManager = Object.FindObjectOfType<QuickMenuManager>();
				}
				_quickMenuManager.inviteFriendsTextAlpha.alpha = 1f;
			}
		}
	}
	[HarmonyPatch(typeof(HUDManager), "SubmitChat_performed")]
	public class RestartLobby_Patch
	{
		private static bool Prefix(HUDManager __instance, ref CallbackContext context)
		{
			if (!((CallbackContext)(ref context)).performed || string.IsNullOrEmpty(__instance.chatTextField.text))
			{
				return true;
			}
			PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController;
			if ((Object)(object)localPlayerController == (Object)null)
			{
				return true;
			}
			StartOfRound playersManager = localPlayerController.playersManager;
			if ((Object)(object)playersManager == (Object)null)
			{
				return true;
			}
			string text = __instance.chatTextField.text;
			if (ChatCommands.verify)
			{
				string text2 = text.ToUpper();
				if (text2 == "CONFIRM" || text2 == "C")
				{
					ResetTextbox(__instance, localPlayerController);
					if (!localPlayerController.isInHangarShipRoom || !playersManager.inShipPhase || playersManager.travellingToNewLevel)
					{
						ChatCommands.SendChatMessage("Cannot restart, ship must be in orbit.");
						return false;
					}
					ChatCommands.AcceptRestart(playersManager);
					return false;
				}
				if (text2 == "DENY" || text2 == "D")
				{
					ResetTextbox(__instance, localPlayerController);
					ChatCommands.DeclineRestart();
					return false;
				}
				return true;
			}
			if (InfernaleModConfig.RestartLobby.Value && text == "/restart")
			{
				ResetTextbox(__instance, localPlayerController);
				if (!GameNetworkManager.Instance.isHostingGame)
				{
					ChatCommands.SendChatMessage("Only the host can restart.");
					return false;
				}
				if (!localPlayerController.isInHangarShipRoom || !playersManager.inShipPhase || playersManager.travellingToNewLevel)
				{
					ChatCommands.SendChatMessage("Cannot restart, ship must be in orbit.");
					return false;
				}
				if (ChatCommands.forceRestart)
				{
					ChatCommands.AcceptRestart(playersManager);
				}
				else
				{
					ChatCommands.ConfirmRestart();
				}
				return false;
			}
			return true;
		}

		private static void ResetTextbox(HUDManager manager, PlayerControllerB local)
		{
			local.isTypingChat = false;
			manager.chatTextField.text = "";
			EventSystem.current.SetSelectedGameObject((GameObject)null);
			manager.PingHUDElement(manager.Chat, 2f, 1f, 0.2f);
			((Behaviour)manager.typingIndicator).enabled = false;
		}
	}
	public static class ChatCommands
	{
		public static bool verify;

		public static bool forceRestart;

		private static MethodInfo chat;

		static ChatCommands()
		{
			verify = false;
			forceRestart = false;
			forceRestart = InfernaleModConfig.ForceRestart.Value;
			chat = AccessTools.Method(typeof(HUDManager), "AddChatMessage", (Type[])null, (Type[])null);
		}

		public static void SendChatMessage(string message)
		{
			chat?.Invoke(HUDManager.Instance, new object[2] { message, "" });
			HUDManager.Instance.lastChatMessage = "";
		}

		public static void ConfirmRestart()
		{
			verify = true;
			SendChatMessage("Are you sure? Type CONFIRM or DENY.");
		}

		public static void AcceptRestart(StartOfRound manager)
		{
			SendChatMessage("Restart confirmed.");
			verify = false;
			int[] array = new int[4]
			{
				manager.gameStats.daysSpent,
				manager.gameStats.scrapValueCollected,
				manager.gameStats.deaths,
				manager.gameStats.allStepsTaken
			};
			manager.FirePlayersAfterDeadlineClientRpc(array, false);
		}

		public static void DeclineRestart()
		{
			SendChatMessage("Restart aborted.");
			verify = false;
		}
	}
	[HarmonyPatch(typeof(HUDManager))]
	public class ShipLoot_Patch
	{
		private static GameObject _totalCounter;

		private static TextMeshProUGUI _textMesh;

		private static float _displayTimeLeft;

		private const float DisplayTime = 3f;

		[HarmonyPatch("PingScan_performed")]
		[HarmonyPrefix]
		public static void ShipLoot(HUDManager __instance)
		{
			if ((Object)(object)GameNetworkManager.Instance.localPlayerController == (Object)null || !InfernaleModConfig.ShipLoot.Value)
			{
				return;
			}
			bool flag = (bool)AccessTools.Method(typeof(HUDManager), "CanPlayerScan", (Type[])null, (Type[])null).Invoke(__instance, null);
			float num = (float)AccessTools.Field(typeof(HUDManager), "playerPingingScan").GetValue(__instance);
			if (!flag || num > -0.5f || (!StartOfRound.Instance.inShipPhase && !GameNetworkManager.Instance.localPlayerController.isInHangarShipRoom))
			{
				return;
			}
			if ((Object)(object)_totalCounter == (Object)null || (Object)(object)_textMesh == (Object)null)
			{
				CopyValueCounter();
				if ((Object)(object)_totalCounter == (Object)null || (Object)(object)_textMesh == (Object)null)
				{
					InfernaleMod.Log.LogError((object)"Failed to initialize _totalCounter or _textMesh.");
					return;
				}
			}
			float num2 = CalculateLootValue();
			((TMP_Text)_textMesh).text = $"SHIP: ${num2:F0}";
			_displayTimeLeft = 3f;
			if (!_totalCounter.activeSelf)
			{
				((MonoBehaviour)GameNetworkManager.Instance).StartCoroutine(ShipLootCoroutine());
			}
		}

		private static IEnumerator ShipLootCoroutine()
		{
			if ((Object)(object)_totalCounter == (Object)null)
			{
				InfernaleMod.Log.LogError((object)"_totalCounter is null or destroyed in ShipLootCoroutine.");
				yield break;
			}
			_totalCounter.SetActive(true);
			while (_displayTimeLeft > 0f)
			{
				if ((Object)(object)_totalCounter == (Object)null)
				{
					InfernaleMod.Log.LogError((object)"_totalCounter is null or destroyed in ShipLootCoroutine.");
					yield break;
				}
				float time = _displayTimeLeft;
				_displayTimeLeft = 0f;
				yield return (object)new WaitForSeconds(time);
			}
			if ((Object)(object)_totalCounter != (Object)null)
			{
				_totalCounter.SetActive(false);
			}
		}

		private static float CalculateLootValue()
		{
			GameObject val = GameObject.Find("/Environment/HangarShip");
			List<GrabbableObject> list = (from obj in val.GetComponentsInChildren<GrabbableObject>()
				where ((Object)obj).name != "ClipboardManual" && ((Object)obj).name != "StickyNoteItem" && ((Object)obj).name != "Key(Clone)" && ((Object)obj).name != "Key"
				select obj).ToList();
			InfernaleMod.Log.LogDebug((object)"Calculating total ship scrap value.");
			CollectionExtensions.Do<GrabbableObject>((IEnumerable<GrabbableObject>)list, (Action<GrabbableObject>)delegate(GrabbableObject scrap)
			{
				InfernaleMod.Log.LogDebug((object)$"{((Object)scrap).name} - ${scrap.scrapValue}");
			});
			return list.Sum((GrabbableObject scrap) => scrap.scrapValue);
		}

		private static void CopyValueCounter()
		{
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: 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_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = GameObject.Find("/Systems/UI/Canvas/IngamePlayerHUD/BottomMiddle/ValueCounter");
			if (!Object.op_Implicit((Object)(object)val))
			{
				InfernaleMod.Log.LogError((object)"Failed to find ValueCounter object to copy!");
				return;
			}
			_totalCounter = Object.Instantiate<GameObject>(val, val.transform.parent, false);
			if ((Object)(object)_totalCounter == (Object)null)
			{
				InfernaleMod.Log.LogError((object)"Failed to instantiate _totalCounter.");
				return;
			}
			_totalCounter.transform.Translate(0f, 1f, 0f);
			Vector3 localPosition = _totalCounter.transform.localPosition;
			_totalCounter.transform.localPosition = new Vector3(localPosition.x + 50f, -50f, localPosition.z);
			_textMesh = _totalCounter.GetComponentInChildren<TextMeshProUGUI>();
			if ((Object)(object)_textMesh == (Object)null)
			{
				InfernaleMod.Log.LogError((object)"Failed to get TextMeshProUGUI from _totalCounter.");
			}
		}
	}
	[HarmonyPatch(typeof(HUDManager))]
	public class ShopHp_Patch
	{
		private static TextMeshProUGUI healthText = null;

		private static readonly Color _healthyColor = Color32.op_Implicit(new Color32((byte)0, byte.MaxValue, (byte)0, byte.MaxValue));

		private static readonly Color _criticalHealthColor = Color32.op_Implicit(new Color32(byte.MaxValue, (byte)0, (byte)0, byte.MaxValue));

		[HarmonyPatch("Awake")]
		[HarmonyPostfix]
		private static void PostfixAwake(HUDManager __instance)
		{
			if (InfernaleModConfig.ShowHp.Value)
			{
				PlayerControllerB val = Object.FindObjectOfType<PlayerControllerB>();
				if ((Object)(object)val != (Object)null)
				{
					int health = val.health;
					HUDManager.Instance.UpdateHealthUI(health, true);
					InfernaleMod.Log.LogInfo((object)"UpdatedHealth");
				}
				else
				{
					InfernaleMod.Log.LogError((object)"PlayerControllerB not found.");
				}
			}
		}

		[HarmonyPatch(typeof(HUDManager), "UpdateHealthUI")]
		[HarmonyPostfix]
		private static void PostfixUpdateHealthUI(HUDManager __instance, int health)
		{
			if ((Object)(object)healthText == (Object)null)
			{
				CreateHealthText(__instance, health);
			}
			UpdateHealthText(health);
			if (health <= 0)
			{
				Object.Destroy((Object)(object)((Component)healthText).gameObject);
				healthText = null;
			}
		}

		private static void UpdateHealthText(int health)
		{
			((TMP_Text)healthText).text = health.ToString();
			UpdateHealthTextColor(health);
		}

		private static void UpdateHealthTextColor(int health)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			double t = (double)health / 100.0;
			((Graphic)healthText).color = ColorInterpolation(_criticalHealthColor, _healthyColor, t);
		}

		private static void CreateHealthText(HUDManager hudManager, int health)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: 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)
			GameObject val = GameObject.Find("Systems/UI/Canvas/IngamePlayerHUD/TopLeftCorner");
			if ((Object)(object)val == (Object)null)
			{
				InfernaleMod.Log.LogError((object)"'TopLeftCorner' not found.");
				return;
			}
			GameObject val2 = new GameObject("PlayerHealthText");
			val2.transform.SetParent(val.transform, false);
			healthText = val2.AddComponent<TextMeshProUGUI>();
			((TMP_Text)healthText).fontSize = 24f;
			((TMP_Text)healthText).alignment = (TextAlignmentOptions)514;
			RectTransform component = val2.GetComponent<RectTransform>();
			component.anchorMin = new Vector2(0f, 1f);
			component.anchorMax = new Vector2(0f, 1f);
			component.pivot = new Vector2(0f, 1f);
			component.anchoredPosition = new Vector2(-28f, -108f);
			UpdateHealthText(health);
		}

		private static Color ParseColor(string rgb)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: 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_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: 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_0075: Unknown result type (might be due to invalid IL or missing references)
			string[] array = rgb.Split(new string[1] { ", " }, StringSplitOptions.RemoveEmptyEntries);
			if (array.Length != 3)
			{
				return Color.white;
			}
			if (float.TryParse(array[0], out var result) && float.TryParse(array[1], out var result2) && float.TryParse(array[2], out var result3))
			{
				return new Color(result / 255f, result2 / 255f, result3 / 255f);
			}
			return Color.white;
		}

		private static Color ColorInterpolation(Color startColor, Color endColor, double t)
		{
			//IL_0001: 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)
			//IL_0015: 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_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: 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)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: 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)
			float num = Mathf.Lerp(startColor.r, endColor.r, (float)t);
			float num2 = Mathf.Lerp(startColor.g, endColor.g, (float)t);
			float num3 = Mathf.Lerp(startColor.b, endColor.b, (float)t);
			float num4 = Mathf.Lerp(startColor.a, endColor.a, (float)t);
			return new Color(num, num2, num3, num4);
		}
	}
	[HarmonyPatch(typeof(Terminal))]
	public class TerminalWalkie_Patch
	{
		public static void SetWalkieMode(bool enabled)
		{
			if (!InfernaleModConfig.TerminalWalkie.Value)
			{
				return;
			}
			InfernaleMod.Log.LogInfo((object)"Terminal opened! Trying to find walkie talkie...");
			PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController;
			InfernaleMod.Log.LogInfo((object)$"There are {localPlayerController.ItemSlots.Length} item slots to check.");
			GrabbableObject val = null;
			for (int i = 0; i < localPlayerController.ItemSlots.Length; i++)
			{
				if (localPlayerController.ItemSlots[i] is WalkieTalkie && (!enabled || localPlayerController.ItemSlots[i].isBeingUsed))
				{
					val = localPlayerController.ItemSlots[i];
					break;
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				InfernaleMod.Log.LogInfo((object)"No active walkie-talkie found in the player inventory!");
				return;
			}
			InfernaleMod.Log.LogInfo((object)"Found an active walkie-talkie! Activating transmission...");
			val.UseItemOnClient(enabled);
		}

		[HarmonyPatch("BeginUsingTerminal")]
		[HarmonyPostfix]
		public static void OpenTerminal()
		{
			SetWalkieMode(enabled: true);
		}

		[HarmonyPatch("QuitTerminal")]
		[HarmonyPostfix]
		public static void CloseTerminal()
		{
			SetWalkieMode(enabled: false);
		}
	}
	[HarmonyPatch(typeof(HUDManager))]
	public class WeightUnit_Patch
	{
		[HarmonyPatch("Update")]
		[HarmonyPostfix]
		public static void WeightUnit(HUDManager __instance)
		{
			if ((Object)(object)GameNetworkManager.Instance != (Object)null && (Object)(object)GameNetworkManager.Instance.localPlayerController != (Object)null)
			{
				if (InfernaleModConfig.WeightUnit.Value)
				{
					float num = Mathf.RoundToInt(Mathf.Clamp(GameNetworkManager.Instance.localPlayerController.carryWeight - 1f, 0f, 100f) * 105f);
					((TMP_Text)__instance.weightCounter).text = string.Format("{0} kg", Mathf.RoundToInt(num * 0.4536f), num);
				}
				else
				{
					float num2 = Mathf.RoundToInt(Mathf.Clamp(GameNetworkManager.Instance.localPlayerController.carryWeight - 1f, 0f, 100f) * 105f);
					((TMP_Text)__instance.weightCounter).text = $"{num2} lb";
				}
			}
		}
	}
}