Decompiled source of ImpostorMod v1.0.7

ImpostorMod.dll

Decompiled 28 minutes ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
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.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("ImpostorMod")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("ImpostorMod")]
[assembly: AssemblyTitle("ImpostorMod")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.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 ImpostorMod
{
	internal static class ImpostorCommands
	{
		private const string Prefix = "/impostor";

		private static void Say(string msg)
		{
			if ((Object)(object)HUDManager.Instance != (Object)null)
			{
				HUDManager.Instance.AddChatMessage("[ImpostorMod] " + msg, "", -1, false);
			}
		}

		internal static bool TryHandle(string raw)
		{
			if (string.IsNullOrWhiteSpace(raw))
			{
				return false;
			}
			string text = raw.Trim();
			if (!text.StartsWith("/impostor", StringComparison.OrdinalIgnoreCase))
			{
				return false;
			}
			if (text.Length > "/impostor".Length && !char.IsWhiteSpace(text["/impostor".Length]))
			{
				return false;
			}
			NetworkManager singleton = NetworkManager.Singleton;
			if ((Object)(object)singleton == (Object)null || !singleton.IsServer)
			{
				Say("Tylko host moze uzywac komend.");
				return true;
			}
			string[] array = text.Substring("/impostor".Length).Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
			string text2 = ((array.Length != 0) ? array[0].ToLowerInvariant() : "help");
			string text3 = ((array.Length > 1) ? array[1].ToLowerInvariant() : null);
			switch (text2)
			{
			case "help":
				Say("/impostor status - pokaz ustawienia");
				Say("/impostor number <n> - liczba impostorow");
				Say("/impostor on | off - wlacz/wylacz role");
				Say("/impostor norepeat on | off - bez powtorek z rzedu");
				Say("/impostor reveal on | off - pokaz impostorow po rundzie");
				Say("/impostor revealdelay <s> - opoznienie po dotarciu na orbite");
				Say("/impostor sabotage on | off - sabotaze impostora");
				Say("/impostor cooldown <s> - odnowienie sabotazy");
				Say("/impostor uses <n> - uzyc sabotazy na impostora/runde");
				Say("/impostor roll - wylosuj role od nowa (po ladowaniu)");
				break;
			case "status":
				Say("Role: " + (Plugin.Enabled.Value ? "WLACZONE" : "wylaczone") + ", " + $"impostorow: {Plugin.ImpostorCount.Value}, " + "bez powtorek: " + (Plugin.NoRepeat.Value ? "tak" : "nie") + ", pokaz impostorow po rundzie: " + (Plugin.RevealEnabled.Value ? "tak" : "nie") + " " + $"(opoznienie {Plugin.RevealDelay.Value}s)");
				Say("Sabotaze: " + (Plugin.SabotageEnabled.Value ? "WLACZONE" : "wylaczone") + ", " + $"odnowienie {Plugin.SabotageCooldown.Value}s, " + $"uzyc na runde {Plugin.SabotageMaxUses.Value}");
				break;
			case "number":
			{
				if (text3 == null || !int.TryParse(text3, out var result4) || result4 < 0 || result4 > 16)
				{
					Say("Uzycie: /impostor number <0-16>");
					break;
				}
				Plugin.ImpostorCount.Value = result4;
				Say($"Liczba impostorow: {result4} (od nastepnego ladowania lub po /impostor roll).");
				break;
			}
			case "on":
				Plugin.Enabled.Value = true;
				Say("Role WLACZONE (od nastepnego ladowania).");
				break;
			case "off":
				Plugin.Enabled.Value = false;
				Plugin.ClearRolesForAll();
				Say("Role WYLACZONE.");
				break;
			case "norepeat":
				if (text3 != "on" && text3 != "off")
				{
					Say("Uzycie: /impostor norepeat on|off");
					break;
				}
				Plugin.NoRepeat.Value = text3 == "on";
				Say("Bez powtorek z rzedu: " + (Plugin.NoRepeat.Value ? "tak" : "nie"));
				break;
			case "reveal":
				if (text3 != "on" && text3 != "off")
				{
					Say("Uzycie: /impostor reveal on|off");
					break;
				}
				Plugin.RevealEnabled.Value = text3 == "on";
				Say("Pokazywanie impostorow po rundzie: " + (Plugin.RevealEnabled.Value ? "tak" : "nie"));
				break;
			case "revealdelay":
			{
				if (text3 == null || !int.TryParse(text3, out var result2) || result2 < 0 || result2 > 60)
				{
					Say("Uzycie: /impostor revealdelay <0-60>");
					break;
				}
				Plugin.RevealDelay.Value = result2;
				Say($"Komunikat o impostorach pojawi sie {result2}s po dotarciu na orbite.");
				break;
			}
			case "sabotage":
				if (text3 != "on" && text3 != "off")
				{
					Say("Uzycie: /impostor sabotage on|off");
					break;
				}
				Plugin.SabotageEnabled.Value = text3 == "on";
				Say("Sabotaze: " + (Plugin.SabotageEnabled.Value ? "WLACZONE" : "wylaczone") + " (od nastepnego ladowania).");
				break;
			case "cooldown":
			{
				if (text3 == null || !int.TryParse(text3, out var result) || result < 0 || result > 600)
				{
					Say("Uzycie: /impostor cooldown <0-600>");
					break;
				}
				Plugin.SabotageCooldown.Value = result;
				Say($"Odnowienie sabotazy: {result}s.");
				break;
			}
			case "uses":
			{
				if (text3 == null || !int.TryParse(text3, out var result3) || result3 < 0 || result3 > 20)
				{
					Say("Uzycie: /impostor uses <0-20>");
					break;
				}
				Plugin.SabotageMaxUses.Value = result3;
				Say($"Uzyc sabotazy na impostora: {result3} (od nastepnego ladowania).");
				break;
			}
			case "roll":
				if (!Plugin.Enabled.Value)
				{
					Say("Role sa wylaczone. Wpisz /impostor on.");
					break;
				}
				if ((Object)(object)StartOfRound.Instance == (Object)null || !StartOfRound.Instance.shipHasLanded)
				{
					Say("Losowanie od nowa dziala tylko, gdy statek stoi na ksiezycu.");
					break;
				}
				Plugin.AssignRoles();
				Say("Wylosowano role od nowa.");
				break;
			default:
				Say("Nieznana komenda. Wpisz /impostor help");
				break;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(HUDManager), "SubmitChat_performed")]
	internal static class ChatSubmitPatch
	{
		[HarmonyPrefix]
		private static void Prefix(HUDManager __instance)
		{
			try
			{
				PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController;
				if (!((Object)(object)val == (Object)null) && val.isTypingChat && ImpostorCommands.TryHandle(__instance.chatTextField.text))
				{
					__instance.chatTextField.text = "";
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Blad komendy czatu: " + ex));
			}
		}
	}
	public enum Role : byte
	{
		Worker = 0,
		Impostor = 1,
		None = byte.MaxValue
	}
	[BepInPlugin("pl.impostormod.lethalcompany", "ImpostorMod", "1.0.7")]
	public class Plugin : BaseUnityPlugin
	{
		private class SabState
		{
			public int Uses;

			public float NextAt;
		}

		[CompilerGenerated]
		private static class <>O
		{
			public static HandleNamedMessageDelegate <0>__OnRoleMessage;

			public static HandleNamedMessageDelegate <1>__OnRevealMessage;

			public static Func<ulong, string> <2>__NameOf;

			public static HandleNamedMessageDelegate <3>__OnSabotageRequest;

			public static HandleNamedMessageDelegate <4>__OnEffectMessage;

			public static HandleNamedMessageDelegate <5>__OnStatusMessage;
		}

		public const string PluginGuid = "pl.impostormod.lethalcompany";

		public const string PluginName = "ImpostorMod";

		public const string PluginVersion = "1.0.7";

		private const string MsgName = "pl.impostormod.lethalcompany.role";

		private const string RevealMsgName = "pl.impostormod.lethalcompany.reveal";

		internal static Plugin Instance;

		internal static ManualLogSource Log;

		internal static ConfigEntry<int> ImpostorCount;

		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<bool> NoRepeat;

		internal static ConfigEntry<bool> RevealEnabled;

		internal static ConfigEntry<int> RevealDuration;

		internal static ConfigEntry<int> RevealDelay;

		internal static ConfigEntry<int> FontSize;

		internal static ConfigEntry<int> OffsetY;

		internal static Role LocalRole = Role.None;

		private static readonly Random Rng = new Random(Guid.NewGuid().GetHashCode());

		internal static readonly HashSet<ulong> LastImpostors = new HashSet<ulong>();

		internal static bool RoundActive;

		internal static List<string> RoundImpostorNames = new List<string>();

		private static bool _hostSeenLanded;

		private static bool _awaitOrbit;

		private static float _leftAt;

		private static float _orbitAt;

		private const string SabotageMsgName = "pl.impostormod.lethalcompany.sabotage";

		private const string EffectMsgName = "pl.impostormod.lethalcompany.effect";

		private const string StatusMsgName = "pl.impostormod.lethalcompany.status";

		private const byte ReqBlackout = 0;

		private const byte ReqDoor = 1;

		private const byte ReqPush = 2;

		private const byte FxBlackoutOn = 0;

		private const byte FxBlackoutOff = 1;

		private const byte FxDoorClose = 2;

		private const byte FxDoorOpen = 3;

		private const byte FxPush = 4;

		internal static ConfigEntry<bool> SabotageEnabled;

		internal static ConfigEntry<int> SabotageCooldown;

		internal static ConfigEntry<int> SabotageMaxUses;

		internal static ConfigEntry<int> BlackoutDuration;

		internal static ConfigEntry<int> DoorDuration;

		internal static ConfigEntry<float> PushForce;

		internal static ConfigEntry<float> PushRange;

		internal static ConfigEntry<Key> BlackoutKey;

		internal static ConfigEntry<Key> DoorKey;

		internal static ConfigEntry<Key> PushKey;

		internal static int SabUsesLeft = -1;

		internal static float SabCooldownUntil;

		private static readonly Dictionary<ulong, SabState> SabStates = new Dictionary<ulong, SabState>();

		private static float _blackoutEnd;

		private static float _doorEnd;

		private void Awake()
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Expected O, but got Unknown
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			ImpostorCount = ((BaseUnityPlugin)this).Config.Bind<int>("Roles", "ImpostorCount", 1, new ConfigDescription("Ilu graczy ma zostac losowo wybranych na impostora w kazdej rundzie. Zawsze zostanie przynajmniej 1 pracownik (gdy gra wiecej niz 1 osoba). Liczy sie tylko config HOSTA.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 16), Array.Empty<object>()));
			Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Roles", "Enabled", true, "Czy losowanie rol jest wlaczone (liczy sie config HOSTA). Mozna zmieniac komenda /impostor on|off.");
			NoRepeat = ((BaseUnityPlugin)this).Config.Bind<bool>("Roles", "NoRepeatImpostor", false, "Jesli true, osoba bedaca impostorem w poprzedniej rundzie nie zostanie nim ponownie (o ile jest kto inny do wylosowania). Komenda /impostor norepeat on|off.");
			RevealEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Reveal", "RevealEnabled", true, "Czy po odlocie statku pokazac wszystkim, kto byl impostorem (liczy sie config HOSTA). Komenda /impostor reveal on|off.");
			RevealDelay = ((BaseUnityPlugin)this).Config.Bind<int>("Reveal", "RevealDelay", 3, new ConfigDescription("Ile sekund PO dotarciu statku na orbite czekac z pokazaniem impostorow (liczy sie config HOSTA). Komenda /impostor revealdelay <sekundy>.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 60), Array.Empty<object>()));
			RevealDuration = ((BaseUnityPlugin)this).Config.Bind<int>("Reveal", "RevealDuration", 8, "Przez ile sekund komunikat o impostorach jest widoczny na srodku ekranu (lokalnie).");
			FontSize = ((BaseUnityPlugin)this).Config.Bind<int>("Display", "FontSize", 36, "Rozmiar napisu z rola na ekranie (lokalnie, kazdy gracz ustawia sobie sam).");
			OffsetY = ((BaseUnityPlugin)this).Config.Bind<int>("Display", "OffsetY", 10, "Odleglosc napisu od gornej krawedzi ekranu w pikselach.");
			BindSabotageConfig();
			new Harmony("pl.impostormod.lethalcompany").PatchAll();
			Log.LogInfo((object)"ImpostorMod 1.0.7 zaladowany.");
		}

		internal static void RegisterHandler()
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Expected O, but got Unknown
			NetworkManager singleton = NetworkManager.Singleton;
			if (!((Object)(object)singleton == (Object)null) && singleton.CustomMessagingManager != null)
			{
				CustomMessagingManager customMessagingManager = singleton.CustomMessagingManager;
				object obj = <>O.<0>__OnRoleMessage;
				if (obj == null)
				{
					HandleNamedMessageDelegate val = OnRoleMessage;
					<>O.<0>__OnRoleMessage = val;
					obj = (object)val;
				}
				customMessagingManager.RegisterNamedMessageHandler("pl.impostormod.lethalcompany.role", (HandleNamedMessageDelegate)obj);
				CustomMessagingManager customMessagingManager2 = singleton.CustomMessagingManager;
				object obj2 = <>O.<1>__OnRevealMessage;
				if (obj2 == null)
				{
					HandleNamedMessageDelegate val2 = OnRevealMessage;
					<>O.<1>__OnRevealMessage = val2;
					obj2 = (object)val2;
				}
				customMessagingManager2.RegisterNamedMessageHandler("pl.impostormod.lethalcompany.reveal", (HandleNamedMessageDelegate)obj2);
				RegisterSabotageHandlers(singleton);
			}
		}

		private static void OnRoleMessage(ulong senderClientId, FastBufferReader reader)
		{
			if (senderClientId == 0L)
			{
				byte role = default(byte);
				((FastBufferReader)(ref reader)).ReadByteSafe(ref role);
				ApplyRole((Role)role);
			}
		}

		private static void OnRevealMessage(ulong senderClientId, FastBufferReader reader)
		{
			if (senderClientId == 0L)
			{
				string payload = default(string);
				((FastBufferReader)(ref reader)).ReadValueSafe(ref payload, false);
				RoleHud.ShowReveal(payload);
			}
		}

		private static void ApplyRole(Role role)
		{
			if (role == Role.None)
			{
				LocalRole = Role.None;
				RoleHud.OnNewRole();
				return;
			}
			LocalRole = role;
			OnRoleApplied();
			RoleHud.OnNewRole();
			Log.LogInfo((object)$"Otrzymano role: {role}");
			if (!((Object)(object)HUDManager.Instance == (Object)null))
			{
				if (role == Role.Impostor)
				{
					HUDManager.Instance.DisplayTip("ROLA: IMPOSTOR (v1.0.7)", "Jestes impostorem. Nikt inny o tym nie wie.", true, false, "LC_Tip1");
				}
				else
				{
					HUDManager.Instance.DisplayTip("ROLA: PRACOWNIK (v1.0.7)", "Jestes pracownikiem.", false, false, "LC_Tip1");
				}
			}
		}

		private unsafe static void SendRole(ulong clientId, Role role)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager singleton = NetworkManager.Singleton;
			if (clientId == singleton.LocalClientId)
			{
				ApplyRole(role);
				return;
			}
			FastBufferWriter val = default(FastBufferWriter);
			((FastBufferWriter)(ref val))..ctor(1, (Allocator)2, -1);
			try
			{
				((FastBufferWriter)(ref val)).WriteByteSafe((byte)role);
				singleton.CustomMessagingManager.SendNamedMessage("pl.impostormod.lethalcompany.role", clientId, val, (NetworkDelivery)3);
			}
			finally
			{
				((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose();
			}
		}

		internal static List<ulong> GetPlayerIds()
		{
			StartOfRound instance = StartOfRound.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				return new List<ulong>();
			}
			return (from p in instance.allPlayerScripts
				where (Object)(object)p != (Object)null && (p.isPlayerControlled || p.isPlayerDead)
				select p.actualClientId).Distinct().ToList();
		}

		internal static void AssignRoles()
		{
			if (!Enabled.Value)
			{
				return;
			}
			List<ulong> playerIds = GetPlayerIds();
			if (playerIds.Count == 0)
			{
				return;
			}
			int num = ((playerIds.Count <= 1) ? 1 : (playerIds.Count - 1));
			int num2 = Mathf.Clamp(ImpostorCount.Value, 0, num);
			List<ulong> source = playerIds;
			if (NoRepeat.Value)
			{
				List<ulong> list = playerIds.Where((ulong i) => !LastImpostors.Contains(i)).ToList();
				if (list.Count >= num2)
				{
					source = list;
				}
			}
			List<ulong> list2 = source.ToList();
			for (int num3 = list2.Count - 1; num3 > 0; num3--)
			{
				int num4 = Rng.Next(num3 + 1);
				List<ulong> list3 = list2;
				int index = num3;
				List<ulong> list4 = list2;
				int index2 = num4;
				ulong value = list2[num4];
				ulong value2 = list2[num3];
				list3[index] = value;
				list4[index2] = value2;
			}
			HashSet<ulong> hashSet = new HashSet<ulong>(list2.Take(num2));
			LastImpostors.Clear();
			foreach (ulong item in hashSet)
			{
				LastImpostors.Add(item);
			}
			RoundImpostorNames = hashSet.Select(NameOf).ToList();
			RoundActive = true;
			_hostSeenLanded = false;
			_awaitOrbit = false;
			foreach (ulong item2 in playerIds)
			{
				SendRole(item2, hashSet.Contains(item2) ? Role.Impostor : Role.Worker);
			}
			InitSabotage(hashSet);
			Log.LogDebug((object)$"Rozlosowano role: graczy={playerIds.Count}, impostorow={num2}.");
		}

		internal static string NameOf(ulong id)
		{
			StartOfRound instance = StartOfRound.Instance;
			if ((Object)(object)instance != (Object)null)
			{
				PlayerControllerB val = ((IEnumerable<PlayerControllerB>)instance.allPlayerScripts).FirstOrDefault((Func<PlayerControllerB, bool>)((PlayerControllerB x) => (Object)(object)x != (Object)null && x.actualClientId == id));
				if ((Object)(object)val != (Object)null && !string.IsNullOrEmpty(val.playerUsername))
				{
					return val.playerUsername;
				}
			}
			return "Gracz " + id;
		}

		internal static void CancelRound(bool broadcastEffects = false)
		{
			ClearEffects(broadcastEffects);
			RoundActive = false;
			_hostSeenLanded = false;
			_awaitOrbit = false;
		}

		internal static void HostTick()
		{
			SabotageTick();
			NetworkManager singleton = NetworkManager.Singleton;
			StartOfRound instance = StartOfRound.Instance;
			if (_awaitOrbit)
			{
				if ((Object)(object)singleton == (Object)null || !singleton.IsServer || (Object)(object)instance == (Object)null)
				{
					_awaitOrbit = false;
					return;
				}
				float unscaledTime = Time.unscaledTime;
				if (_orbitAt < 0f && instance.inShipPhase && !instance.shipHasLanded)
				{
					_orbitAt = unscaledTime;
				}
				bool num = _orbitAt >= 0f && unscaledTime - _orbitAt >= (float)RevealDelay.Value;
				bool flag = unscaledTime - _leftAt > 45f;
				if (num || flag)
				{
					_awaitOrbit = false;
					if (RevealEnabled.Value)
					{
						SendReveal();
					}
				}
			}
			else if (!RoundActive)
			{
				_hostSeenLanded = false;
			}
			else if (!((Object)(object)singleton == (Object)null) && singleton.IsServer && !((Object)(object)instance == (Object)null))
			{
				if (instance.shipHasLanded)
				{
					_hostSeenLanded = true;
				}
				else if (_hostSeenLanded)
				{
					RoundActive = false;
					_hostSeenLanded = false;
					ClearEffects(broadcast: true);
					_awaitOrbit = true;
					_leftAt = Time.unscaledTime;
					_orbitAt = -1f;
				}
			}
		}

		private unsafe static void SendReveal()
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager singleton = NetworkManager.Singleton;
			string text = string.Join("|", RoundImpostorNames);
			FastBufferWriter val = default(FastBufferWriter);
			foreach (ulong playerId in GetPlayerIds())
			{
				if (playerId == singleton.LocalClientId)
				{
					RoleHud.ShowReveal(text);
					continue;
				}
				((FastBufferWriter)(ref val))..ctor(FastBufferWriter.GetWriteSize(text, false), (Allocator)2, -1);
				try
				{
					((FastBufferWriter)(ref val)).WriteValueSafe(text, false);
					singleton.CustomMessagingManager.SendNamedMessage("pl.impostormod.lethalcompany.reveal", playerId, val, (NetworkDelivery)3);
				}
				finally
				{
					((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose();
				}
			}
		}

		internal static void ClearRolesForAll()
		{
			CancelRound(broadcastEffects: true);
			foreach (ulong playerId in GetPlayerIds())
			{
				SendRole(playerId, Role.None);
			}
		}

		private void BindSabotageConfig()
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Expected O, but got Unknown
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Expected O, but got Unknown
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Expected O, but got Unknown
			SabotageEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Sabotage", "SabotageEnabled", true, "Czy impostor moze uzywac sabotazy (liczy sie config HOSTA). Komenda /impostor sabotage on|off.");
			SabotageCooldown = ((BaseUnityPlugin)this).Config.Bind<int>("Sabotage", "Cooldown", 60, new ConfigDescription("Czas odnowienia miedzy sabotazami (sekundy, liczy sie config HOSTA). Komenda /impostor cooldown <s>.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 600), Array.Empty<object>()));
			SabotageMaxUses = ((BaseUnityPlugin)this).Config.Bind<int>("Sabotage", "MaxUsesPerRound", 3, new ConfigDescription("Ile sabotazy moze uzyc KAZDY impostor w jednej rundzie (liczy sie config HOSTA). Komenda /impostor uses <n>.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 20), Array.Empty<object>()));
			BlackoutDuration = ((BaseUnityPlugin)this).Config.Bind<int>("Sabotage", "BlackoutDuration", 10, new ConfigDescription("Ile sekund trwa zgaszenie swiatel (HOST).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 60), Array.Empty<object>()));
			DoorDuration = ((BaseUnityPlugin)this).Config.Bind<int>("Sabotage", "DoorDuration", 8, new ConfigDescription("Ile sekund drzwi statku zostaja zamkniete (HOST).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 60), Array.Empty<object>()));
			PushForce = ((BaseUnityPlugin)this).Config.Bind<float>("Sabotage", "PushForce", 1000f, "Sila popchniecia (HOST). Wieksza = dalej odrzuca.");
			PushRange = ((BaseUnityPlugin)this).Config.Bind<float>("Sabotage", "PushRange", 3.5f, "Maksymalna odleglosc od impostora, z jakiej mozna popchnac najblizszego gracza (HOST).");
			BlackoutKey = ((BaseUnityPlugin)this).Config.Bind<Key>("Sabotage", "BlackoutKey", (Key)36, "Klawisz: zgaszenie swiatel (lokalnie).");
			DoorKey = ((BaseUnityPlugin)this).Config.Bind<Key>("Sabotage", "DoorKey", (Key)16, "Klawisz: zamkniecie drzwi statku (lokalnie).");
			PushKey = ((BaseUnityPlugin)this).Config.Bind<Key>("Sabotage", "PushKey", (Key)17, "Klawisz: popchniecie najblizszego gracza (lokalnie).");
		}

		private static void RegisterSabotageHandlers(NetworkManager nm)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Expected O, but got Unknown
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Expected O, but got Unknown
			CustomMessagingManager customMessagingManager = nm.CustomMessagingManager;
			object obj = <>O.<3>__OnSabotageRequest;
			if (obj == null)
			{
				HandleNamedMessageDelegate val = OnSabotageRequest;
				<>O.<3>__OnSabotageRequest = val;
				obj = (object)val;
			}
			customMessagingManager.RegisterNamedMessageHandler("pl.impostormod.lethalcompany.sabotage", (HandleNamedMessageDelegate)obj);
			object obj2 = <>O.<4>__OnEffectMessage;
			if (obj2 == null)
			{
				HandleNamedMessageDelegate val2 = OnEffectMessage;
				<>O.<4>__OnEffectMessage = val2;
				obj2 = (object)val2;
			}
			customMessagingManager.RegisterNamedMessageHandler("pl.impostormod.lethalcompany.effect", (HandleNamedMessageDelegate)obj2);
			object obj3 = <>O.<5>__OnStatusMessage;
			if (obj3 == null)
			{
				HandleNamedMessageDelegate val3 = OnStatusMessage;
				<>O.<5>__OnStatusMessage = val3;
				obj3 = (object)val3;
			}
			customMessagingManager.RegisterNamedMessageHandler("pl.impostormod.lethalcompany.status", (HandleNamedMessageDelegate)obj3);
		}

		internal static void OnRoleApplied()
		{
			SabUsesLeft = -1;
			SabCooldownUntil = 0f;
		}

		internal static void HandleSabotageKeys()
		{
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			Keyboard current = Keyboard.current;
			if (current == null)
			{
				return;
			}
			PlayerControllerB val = (((Object)(object)GameNetworkManager.Instance != (Object)null) ? GameNetworkManager.Instance.localPlayerController : null);
			if (!((Object)(object)val == (Object)null) && !val.isTypingChat && !val.isPlayerDead && !Refl.GetBool(val, "inTerminalMenu"))
			{
				if (((ButtonControl)current[BlackoutKey.Value]).wasPressedThisFrame)
				{
					RequestSabotage(0);
				}
				else if (((ButtonControl)current[DoorKey.Value]).wasPressedThisFrame)
				{
					RequestSabotage(1);
				}
				else if (((ButtonControl)current[PushKey.Value]).wasPressedThisFrame)
				{
					RequestSabotage(2);
				}
			}
		}

		private static void Tip(string text)
		{
			if ((Object)(object)HUDManager.Instance != (Object)null)
			{
				HUDManager.Instance.DisplayTip("SABOTAZ", text, false, false, "LC_Tip1");
			}
		}

		internal unsafe static void RequestSabotage(byte type)
		{
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager singleton = NetworkManager.Singleton;
			if ((Object)(object)singleton == (Object)null || SabUsesLeft == 255)
			{
				return;
			}
			float unscaledTime = Time.unscaledTime;
			if (SabUsesLeft == 0)
			{
				Tip("Wykorzystales wszystkie sabotaze w tej rundzie.");
				return;
			}
			if (unscaledTime < SabCooldownUntil)
			{
				Tip("Odnowienie: " + Mathf.CeilToInt(SabCooldownUntil - unscaledTime) + " s");
				return;
			}
			if (singleton.IsServer)
			{
				TryExecuteSabotage(singleton.LocalClientId, type);
				return;
			}
			FastBufferWriter val = default(FastBufferWriter);
			((FastBufferWriter)(ref val))..ctor(1, (Allocator)2, -1);
			try
			{
				((FastBufferWriter)(ref val)).WriteByteSafe(type);
				singleton.CustomMessagingManager.SendNamedMessage("pl.impostormod.lethalcompany.sabotage", 0uL, val, (NetworkDelivery)3);
			}
			finally
			{
				((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose();
			}
		}

		internal static string SabotageHint()
		{
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: 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_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			if (SabUsesLeft < 0 || SabUsesLeft == 255)
			{
				return "";
			}
			float num = SabCooldownUntil - Time.unscaledTime;
			string text = ((SabUsesLeft == 0) ? "brak uzyc" : ((num > 0f) ? ("odnowienie " + Mathf.CeilToInt(num) + " s") : "gotowe"));
			return "\n<size=45%><color=#FFFFFF>[" + ((object)BlackoutKey.Value/*cast due to .constrained prefix*/).ToString() + "] Ciemnosc  [" + ((object)DoorKey.Value/*cast due to .constrained prefix*/).ToString() + "] Drzwi  [" + ((object)PushKey.Value/*cast due to .constrained prefix*/).ToString() + "] Popchniecie\nSabotaze: " + SabUsesLeft + " | " + text + "</color></size>";
		}

		private static void ApplyStatus(byte uses, float cooldown, string text)
		{
			SabUsesLeft = uses;
			SabCooldownUntil = Time.unscaledTime + Mathf.Max(0f, cooldown);
			if (!string.IsNullOrEmpty(text))
			{
				Tip(text);
			}
		}

		private static void OnStatusMessage(ulong sender, FastBufferReader reader)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			if (sender == 0L)
			{
				byte uses = default(byte);
				((FastBufferReader)(ref reader)).ReadByteSafe(ref uses);
				float cooldown = default(float);
				((FastBufferReader)(ref reader)).ReadValueSafe<float>(ref cooldown, default(ForPrimitives));
				string text = default(string);
				((FastBufferReader)(ref reader)).ReadValueSafe(ref text, false);
				ApplyStatus(uses, cooldown, text);
			}
		}

		private static void OnEffectMessage(ulong sender, FastBufferReader reader)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: 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)
			if (sender == 0L)
			{
				byte type = default(byte);
				((FastBufferReader)(ref reader)).ReadByteSafe(ref type);
				float x = default(float);
				((FastBufferReader)(ref reader)).ReadValueSafe<float>(ref x, default(ForPrimitives));
				float z = default(float);
				((FastBufferReader)(ref reader)).ReadValueSafe<float>(ref z, default(ForPrimitives));
				ApplyEffect(type, x, z);
			}
		}

		internal static void InitSabotage(HashSet<ulong> impostors)
		{
			ClearEffects(broadcast: true);
			SabStates.Clear();
			foreach (ulong impostor in impostors)
			{
				SabStates[impostor] = new SabState
				{
					Uses = SabotageMaxUses.Value,
					NextAt = 0f
				};
				SendStatus(impostor, SabotageEnabled.Value ? ((byte)SabotageMaxUses.Value) : byte.MaxValue, 0f, "");
			}
		}

		private static void OnSabotageRequest(ulong sender, FastBufferReader reader)
		{
			NetworkManager singleton = NetworkManager.Singleton;
			if (!((Object)(object)singleton == (Object)null) && singleton.IsServer)
			{
				byte type = default(byte);
				((FastBufferReader)(ref reader)).ReadByteSafe(ref type);
				TryExecuteSabotage(sender, type);
			}
		}

		private static PlayerControllerB PlayerById(ulong id)
		{
			StartOfRound instance = StartOfRound.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				return null;
			}
			return ((IEnumerable<PlayerControllerB>)instance.allPlayerScripts).FirstOrDefault((Func<PlayerControllerB, bool>)((PlayerControllerB p) => (Object)(object)p != (Object)null && p.actualClientId == id));
		}

		private static void Reply(ulong id, SabState st, string text)
		{
			float cooldown = Mathf.Max(0f, st.NextAt - Time.unscaledTime);
			SendStatus(id, (byte)Mathf.Max(0, st.Uses), cooldown, text);
		}

		internal static void TryExecuteSabotage(ulong id, byte type)
		{
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_023d: Unknown result type (might be due to invalid IL or missing references)
			//IL_024c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0251: Unknown result type (might be due to invalid IL or missing references)
			//IL_025b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0262: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			//IL_0239: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			if (!RoundActive || !LastImpostors.Contains(id) || !SabStates.TryGetValue(id, out var value) || !SabotageEnabled.Value)
			{
				return;
			}
			StartOfRound instance = StartOfRound.Instance;
			PlayerControllerB val = PlayerById(id);
			if ((Object)(object)instance == (Object)null || (Object)(object)val == (Object)null || val.isPlayerDead)
			{
				return;
			}
			if (!instance.shipHasLanded)
			{
				Reply(id, value, "Sabotaz mozliwy tylko, gdy statek stoi na ksiezycu.");
				return;
			}
			if (value.Uses <= 0)
			{
				Reply(id, value, "Wykorzystales wszystkie sabotaze w tej rundzie.");
				return;
			}
			float unscaledTime = Time.unscaledTime;
			if (unscaledTime < value.NextAt)
			{
				Reply(id, value, "Odnowienie: " + Mathf.CeilToInt(value.NextAt - unscaledTime) + " s");
				return;
			}
			string text;
			switch (type)
			{
			default:
				return;
			case 0:
				if (_blackoutEnd > 0f)
				{
					Reply(id, value, "Swiatla sa juz zgaszone.");
					return;
				}
				_blackoutEnd = unscaledTime + (float)BlackoutDuration.Value;
				BroadcastEffect(0, 0f, 0f);
				text = "Zgaszono swiatla.";
				break;
			case 1:
				if (_doorEnd > 0f)
				{
					Reply(id, value, "Drzwi statku sa juz zamkniete.");
					return;
				}
				_doorEnd = unscaledTime + (float)DoorDuration.Value;
				BroadcastEffect(2, 0f, 0f);
				text = "Zamknieto drzwi statku.";
				break;
			case 2:
			{
				PlayerControllerB val2 = null;
				float num = PushRange.Value;
				Vector3 position = ((Component)val).transform.position;
				PlayerControllerB[] allPlayerScripts = instance.allPlayerScripts;
				foreach (PlayerControllerB val3 in allPlayerScripts)
				{
					if (!((Object)(object)val3 == (Object)null) && !((Object)(object)val3 == (Object)(object)val) && val3.isPlayerControlled && !val3.isPlayerDead)
					{
						float num2 = Vector3.Distance(((Component)val3).transform.position, position);
						if (num2 <= num)
						{
							val2 = val3;
							num = num2;
						}
					}
				}
				if ((Object)(object)val2 == (Object)null)
				{
					Reply(id, value, "Nikogo nie ma w poblizu.");
					return;
				}
				Vector3 val4 = ((Component)val2).transform.position - position;
				val4.y = 0f;
				if (((Vector3)(ref val4)).sqrMagnitude < 0.01f)
				{
					val4 = ((Component)val).transform.forward;
				}
				val4 = ((Vector3)(ref val4)).normalized * PushForce.Value;
				SendEffect(val2.actualClientId, 4, val4.x, val4.z);
				text = "Popchnieto: " + val2.playerUsername;
				break;
			}
			}
			value.Uses--;
			value.NextAt = unscaledTime + (float)SabotageCooldown.Value;
			Reply(id, value, text);
		}

		internal static void SabotageTick()
		{
			if (_blackoutEnd <= 0f && _doorEnd <= 0f)
			{
				return;
			}
			NetworkManager singleton = NetworkManager.Singleton;
			if ((Object)(object)singleton == (Object)null || !singleton.IsServer)
			{
				_blackoutEnd = 0f;
				_doorEnd = 0f;
				return;
			}
			float unscaledTime = Time.unscaledTime;
			if (_blackoutEnd > 0f && unscaledTime >= _blackoutEnd)
			{
				_blackoutEnd = 0f;
				BroadcastEffect(1, 0f, 0f);
			}
			if (_doorEnd > 0f && unscaledTime >= _doorEnd)
			{
				_doorEnd = 0f;
				BroadcastEffect(3, 0f, 0f);
			}
		}

		internal static void ClearEffects(bool broadcast)
		{
			try
			{
				if (_blackoutEnd > 0f)
				{
					_blackoutEnd = 0f;
					if (broadcast)
					{
						BroadcastEffect(1, 0f, 0f);
					}
				}
				if (_doorEnd > 0f)
				{
					_doorEnd = 0f;
					if (broadcast)
					{
						BroadcastEffect(3, 0f, 0f);
					}
				}
			}
			catch (Exception ex)
			{
				Log.LogError((object)("Blad konczenia efektow: " + ex));
			}
		}

		private unsafe static void SendStatus(ulong id, byte uses, float cooldown, string text)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager singleton = NetworkManager.Singleton;
			text = text ?? "";
			if (id == singleton.LocalClientId)
			{
				ApplyStatus(uses, cooldown, text);
				return;
			}
			FastBufferWriter val = default(FastBufferWriter);
			((FastBufferWriter)(ref val))..ctor(5 + FastBufferWriter.GetWriteSize(text, false), (Allocator)2, -1);
			try
			{
				((FastBufferWriter)(ref val)).WriteByteSafe(uses);
				((FastBufferWriter)(ref val)).WriteValueSafe<float>(ref cooldown, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe(text, false);
				singleton.CustomMessagingManager.SendNamedMessage("pl.impostormod.lethalcompany.status", id, val, (NetworkDelivery)3);
			}
			finally
			{
				((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose();
			}
		}

		private unsafe static void SendEffect(ulong id, byte type, float x, float z)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: 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_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager singleton = NetworkManager.Singleton;
			if (id == singleton.LocalClientId)
			{
				ApplyEffect(type, x, z);
				return;
			}
			FastBufferWriter val = default(FastBufferWriter);
			((FastBufferWriter)(ref val))..ctor(9, (Allocator)2, -1);
			try
			{
				((FastBufferWriter)(ref val)).WriteByteSafe(type);
				((FastBufferWriter)(ref val)).WriteValueSafe<float>(ref x, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<float>(ref z, default(ForPrimitives));
				singleton.CustomMessagingManager.SendNamedMessage("pl.impostormod.lethalcompany.effect", id, val, (NetworkDelivery)3);
			}
			finally
			{
				((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose();
			}
		}

		private static void BroadcastEffect(byte type, float x, float z)
		{
			foreach (ulong playerId in GetPlayerIds())
			{
				SendEffect(playerId, type, x, z);
			}
		}

		private static void ApplyEffect(byte type, float x, float z)
		{
			try
			{
				switch (type)
				{
				case 0:
					SetPower(on: false);
					break;
				case 1:
					SetPower(on: true);
					break;
				case 2:
					SetDoor(closed: true);
					break;
				case 3:
					SetDoor(closed: false);
					break;
				case 4:
					Push(x, z);
					break;
				}
			}
			catch (Exception ex)
			{
				Log.LogError((object)("Blad efektu " + type + ": " + ex));
			}
		}

		private static void SetPower(bool on)
		{
			RoundManager instance = RoundManager.Instance;
			if ((Object)(object)instance != (Object)null && (!on || !Refl.GetBool(instance, "powerOffPermanently")))
			{
				Refl.Call(instance, "SwitchPower", on);
			}
			StartOfRound instance2 = StartOfRound.Instance;
			if ((Object)(object)instance2 != (Object)null)
			{
				Refl.Call(Refl.GetField(instance2, "shipRoomLights"), "SetShipLightsBoolean", on);
			}
		}

		private static void SetDoor(bool closed)
		{
			Type type = AccessTools.TypeByName("HangarShipDoor");
			if (type == null)
			{
				Refl.Warn("Nie znaleziono klasy HangarShipDoor.");
				return;
			}
			Refl.Call(Object.FindObjectOfType(type), "PlayDoorAnimation", closed);
		}

		private static void Push(float x, float z)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			PlayerControllerB val = (((Object)(object)GameNetworkManager.Instance != (Object)null) ? GameNetworkManager.Instance.localPlayerController : null);
			if (!((Object)(object)val == (Object)null) && !val.isPlayerDead)
			{
				Vector3 val2 = ((Refl.GetField(val, "externalForces") is Vector3 val3) ? val3 : Vector3.zero);
				Refl.SetField(val, "externalForces", val2 + new Vector3(x, 0f, z));
			}
		}
	}
	internal static class RoleHud
	{
		private static TextMeshProUGUI _text;

		private static bool _seenLanded;

		private static bool _loggedCreated;

		private static TextMeshProUGUI _revealText;

		private static float _revealUntil;

		private static string _revealPending;

		internal static void OnNewRole()
		{
			_seenLanded = false;
		}

		internal static void Tick(HUDManager hud)
		{
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			TickReveal(hud);
			if (Plugin.LocalRole != Role.None)
			{
				StartOfRound instance = StartOfRound.Instance;
				if ((Object)(object)instance == (Object)null)
				{
					Plugin.LocalRole = Role.None;
				}
				else if (instance.shipHasLanded)
				{
					_seenLanded = true;
				}
				else if (_seenLanded)
				{
					Plugin.LocalRole = Role.None;
				}
			}
			if (Plugin.LocalRole == Role.Impostor)
			{
				Plugin.HandleSabotageKeys();
			}
			if (Plugin.LocalRole == Role.None)
			{
				if ((Object)(object)_text != (Object)null)
				{
					((Component)_text).gameObject.SetActive(false);
				}
				return;
			}
			try
			{
				if ((Object)(object)_text == (Object)null)
				{
					Create(hud);
				}
				if (!((Object)(object)_text == (Object)null))
				{
					bool flag = Plugin.LocalRole == Role.Impostor;
					((TMP_Text)_text).text = (flag ? ("IMPOSTOR" + Plugin.SabotageHint()) : "PRACOWNIK");
					((Graphic)_text).color = (flag ? new Color(0.95f, 0.05f, 0.05f, 1f) : new Color(0.55f, 0.85f, 1f, 1f));
					((TMP_Text)_text).fontSize = Plugin.FontSize.Value;
					((Component)_text).gameObject.SetActive(true);
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Blad napisu roli: " + ex));
			}
		}

		internal static void ShowReveal(string payload)
		{
			List<string> list = (from n in (payload ?? "").Split(new char[1] { '|' }, StringSplitOptions.RemoveEmptyEntries)
				select n.Replace("<", "").Replace(">", "")).ToList();
			string revealPending = ((list.Count != 0) ? (((list.Count == 1) ? "Impostor w tej rundzie:" : "Impostorzy w tej rundzie:") + "\n<color=#F20D0D><b>" + string.Join(", ", list) + "</b></color>") : "W tej rundzie nie bylo impostora.");
			_revealPending = revealPending;
			_revealUntil = Time.unscaledTime + (float)Mathf.Max(1, Plugin.RevealDuration.Value);
		}

		private static void TickReveal(HUDManager hud)
		{
			try
			{
				if (_revealPending == null && ((Object)(object)_revealText == (Object)null || Time.unscaledTime >= _revealUntil))
				{
					if ((Object)(object)_revealText != (Object)null)
					{
						((Component)_revealText).gameObject.SetActive(false);
					}
					return;
				}
				if ((Object)(object)_revealText == (Object)null)
				{
					CreateReveal(hud);
				}
				if (!((Object)(object)_revealText == (Object)null))
				{
					if (_revealPending != null)
					{
						((TMP_Text)_revealText).text = _revealPending;
						_revealPending = null;
					}
					bool active = Time.unscaledTime < _revealUntil;
					((Component)_revealText).gameObject.SetActive(active);
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Blad komunikatu o impostorach: " + ex));
				_revealPending = null;
			}
		}

		private static void CreateReveal(HUDManager hud)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: 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_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			Transform val = (((Object)(object)hud.HUDContainer != (Object)null) ? hud.HUDContainer.transform : ((Component)hud).transform);
			GameObject val2 = new GameObject("ImpostorModRevealText", new Type[1] { typeof(RectTransform) })
			{
				layer = ((Component)val).gameObject.layer
			};
			val2.transform.SetParent(val, false);
			val2.transform.SetAsLastSibling();
			RectTransform component = val2.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(0f, 60f);
			component.sizeDelta = new Vector2(1200f, 300f);
			((Transform)component).localScale = Vector3.one;
			TextMeshProUGUI val3 = val2.AddComponent<TextMeshProUGUI>();
			TMP_FontAsset val4 = null;
			if (hud.controlTipLines != null && hud.controlTipLines.Length != 0 && (Object)(object)hud.controlTipLines[0] != (Object)null)
			{
				val4 = ((TMP_Text)hud.controlTipLines[0]).font;
			}
			if ((Object)(object)val4 == (Object)null)
			{
				val4 = TMP_Settings.defaultFontAsset;
			}
			if ((Object)(object)val4 != (Object)null)
			{
				((TMP_Text)val3).font = val4;
			}
			((TMP_Text)val3).alignment = (TextAlignmentOptions)514;
			((TMP_Text)val3).fontSize = 48f;
			((Graphic)val3).color = Color.white;
			((TMP_Text)val3).enableWordWrapping = true;
			((Graphic)val3).raycastTarget = false;
			((TMP_Text)val3).overflowMode = (TextOverflowModes)0;
			_revealText = val3;
		}

		private static void Create(HUDManager hud)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: 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_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			Transform val = (((Object)(object)hud.HUDContainer != (Object)null) ? hud.HUDContainer.transform : ((Component)hud).transform);
			GameObject val2 = new GameObject("ImpostorModRoleText", new Type[1] { typeof(RectTransform) })
			{
				layer = ((Component)val).gameObject.layer
			};
			val2.transform.SetParent(val, false);
			val2.transform.SetAsLastSibling();
			RectTransform component = val2.GetComponent<RectTransform>();
			component.anchorMin = new Vector2(1f, 1f);
			component.anchorMax = new Vector2(1f, 1f);
			component.pivot = new Vector2(1f, 1f);
			component.anchoredPosition = new Vector2(-20f, (float)(-Plugin.OffsetY.Value));
			component.sizeDelta = new Vector2(700f, 180f);
			((Transform)component).localScale = Vector3.one;
			TextMeshProUGUI val3 = val2.AddComponent<TextMeshProUGUI>();
			TMP_FontAsset val4 = null;
			if (hud.controlTipLines != null && hud.controlTipLines.Length != 0 && (Object)(object)hud.controlTipLines[0] != (Object)null)
			{
				val4 = ((TMP_Text)hud.controlTipLines[0]).font;
			}
			if ((Object)(object)val4 == (Object)null)
			{
				val4 = TMP_Settings.defaultFontAsset;
			}
			if ((Object)(object)val4 != (Object)null)
			{
				((TMP_Text)val3).font = val4;
			}
			((TMP_Text)val3).alignment = (TextAlignmentOptions)260;
			((TMP_Text)val3).fontStyle = (FontStyles)1;
			((TMP_Text)val3).enableWordWrapping = false;
			((Graphic)val3).raycastTarget = false;
			((TMP_Text)val3).overflowMode = (TextOverflowModes)0;
			_text = val3;
			if (!_loggedCreated)
			{
				_loggedCreated = true;
				Plugin.Log.LogInfo((object)("Utworzono napis roli (rodzic: " + ((Object)val).name + ", font: " + (((Object)(object)val4 != (Object)null) ? ((Object)val4).name : "brak") + ")."));
			}
		}
	}
	[HarmonyPatch(typeof(HUDManager), "Update")]
	internal static class HudUpdatePatch
	{
		[HarmonyPostfix]
		private static void Postfix(HUDManager __instance)
		{
			Plugin.HostTick();
			RoleHud.Tick(__instance);
		}
	}
	[HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")]
	internal static class ConnectPatch
	{
		[HarmonyPostfix]
		private static void Postfix()
		{
			Plugin.RegisterHandler();
		}
	}
	[HarmonyPatch(typeof(StartOfRound), "OnShipLandedMiscEvents")]
	internal static class LandingPatch
	{
		[HarmonyPostfix]
		private static void Postfix()
		{
			NetworkManager singleton = NetworkManager.Singleton;
			if ((Object)(object)singleton != (Object)null && singleton.IsServer)
			{
				Plugin.AssignRoles();
			}
		}
	}
	[HarmonyPatch(typeof(GameNetworkManager), "Disconnect")]
	internal static class DisconnectPatch
	{
		[HarmonyPostfix]
		private static void Postfix()
		{
			Plugin.LocalRole = Role.None;
			Plugin.LastImpostors.Clear();
			Plugin.CancelRound();
		}
	}
	internal static class Refl
	{
		private static readonly HashSet<string> Warned = new HashSet<string>();

		private const BindingFlags All = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

		internal static void Warn(string msg)
		{
			Plugin.Log.LogWarning((object)msg);
			if (!Warned.Add(msg))
			{
				return;
			}
			try
			{
				if ((Object)(object)HUDManager.Instance != (Object)null)
				{
					HUDManager.Instance.AddChatMessage("[ImpostorMod] " + msg, "", -1, false);
				}
			}
			catch
			{
			}
		}

		internal static object Call(object target, string name, params object[] args)
		{
			if (target == null)
			{
				Warn("Brak obiektu dla: " + name);
				return null;
			}
			Type type = target.GetType();
			while (type != null)
			{
				MethodInfo[] methods = type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (MethodInfo methodInfo in methods)
				{
					if (!(methodInfo.Name != name) && methodInfo.GetParameters().Length == args.Length)
					{
						try
						{
							return methodInfo.Invoke(target, args);
						}
						catch (Exception ex)
						{
							Warn("Blad wywolania " + name + ": " + (ex.InnerException ?? ex).Message);
							return null;
						}
					}
				}
				type = type.BaseType;
			}
			Warn("Nie znaleziono metody " + name + " w " + target.GetType().Name + ".");
			return null;
		}

		private static FieldInfo FindField(object target, string name)
		{
			Type type = target.GetType();
			while (type != null)
			{
				FieldInfo field = type.GetField(name, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field != null)
				{
					return field;
				}
				type = type.BaseType;
			}
			return null;
		}

		internal static object GetField(object target, string name)
		{
			if (target == null)
			{
				return null;
			}
			FieldInfo fieldInfo = FindField(target, name);
			if (fieldInfo == null)
			{
				Warn("Nie znaleziono pola " + name + " w " + target.GetType().Name + ".");
				return null;
			}
			return fieldInfo.GetValue(target);
		}

		internal static void SetField(object target, string name, object value)
		{
			if (target != null)
			{
				FieldInfo fieldInfo = FindField(target, name);
				if (fieldInfo == null)
				{
					Warn("Nie znaleziono pola " + name + " w " + target.GetType().Name + ".");
				}
				else
				{
					fieldInfo.SetValue(target, value);
				}
			}
		}

		internal static bool GetBool(object target, string name)
		{
			if (target == null)
			{
				return false;
			}
			FieldInfo fieldInfo = FindField(target, name);
			bool flag = default(bool);
			int num;
			if (fieldInfo != null)
			{
				object value = fieldInfo.GetValue(target);
				if (value is bool)
				{
					flag = (bool)value;
					num = 1;
				}
				else
				{
					num = 0;
				}
			}
			else
			{
				num = 0;
			}
			return (byte)((uint)num & (flag ? 1u : 0u)) != 0;
		}
	}
}