Decompiled source of ImpostorAmongus v0.1.0

plugins/ImpostorAmongus/Amogus.dll

Decompiled 10 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using Amogus.API;
using Amogus.Affiliations;
using Amogus.Behaviours;
using Amogus.NetcodePatcher;
using Amogus.Patches;
using Amogus.Util;
using BepInEx;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
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: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: AssemblyCompany("Amogus")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("Amogus")]
[assembly: AssemblyTitle("Amogus")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
[module: NetcodePatchedAssembly]
internal class <Module>
{
	static <Module>()
	{
	}
}
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 Amogus
{
	[BepInPlugin("me.loaforc.amogus", "Amogus", "0.1.0")]
	public class AmogusPlugin : BaseUnityPlugin
	{
		public const string MOD_GUID = "me.loaforc.amogus";

		public const string MOD_NAME = "Amogus";

		public const string MOD_VERSION = "0.1.0";

		internal static AmogusPlugin instance;

		internal static ManualLogSource logger;

		internal static RoleInfo Crewmate;

		internal static RoleInfo Impostor;

		private void Awake()
		{
			if (!((Object)(object)instance == (Object)null))
			{
				return;
			}
			instance = this;
			logger = Logger.CreateLogSource("me.loaforc.amogus");
			logger.LogInfo((object)"assets");
			Assets.Init();
			logger.LogInfo((object)"networking");
			Type[] types = Assembly.GetExecutingAssembly().GetTypes();
			foreach (Type type in types)
			{
				try
				{
					MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic);
					foreach (MethodInfo methodInfo in methods)
					{
						if (methodInfo.GetCustomAttributes(typeof(RuntimeInitializeOnLoadMethodAttribute), inherit: false).Length != 0)
						{
							methodInfo.Invoke(null, null);
						}
					}
				}
				catch (Exception ex)
				{
					logger.LogWarning((object)("CAUGHT EXCEPTION: " + ex));
					logger.LogInfo((object)"");
					logger.LogWarning((object)"======================================================");
					logger.LogWarning((object)"The error above can most likely be ignored");
					logger.LogWarning((object)"======================================================");
					logger.LogInfo((object)"");
				}
			}
			logger.LogInfo((object)"patching");
			Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "me.loaforc.amogus");
			logger.LogInfo((object)"Registering roles.");
			Crewmate = new RoleInfo(AmogusAPI.Crewmate, Assets.crewmateHandler)
			{
				Name = "Crewmate",
				MinPlayers = 0,
				MaxPlayers = 999
			};
			Impostor = new RoleInfo(AmogusAPI.Impostor, Assets.impostorHandler)
			{
				Name = "Impostor",
				MinPlayers = 1,
				MaxPlayers = 1
			};
			AmogusAPI.RegisterRole(Crewmate);
			AmogusAPI.RegisterRole(Impostor);
			logger.LogInfo((object)"Amogus:0.1.0 has succesfully loaded!");
		}
	}
}
namespace Amogus.Util
{
	internal class AmogusConfig
	{
		public static bool LOG_ROLE_CHANGES = false;

		public static int QUOTAS_TILL_CREWMATE_WIN = 3;
	}
	internal static class Assets
	{
		internal static AssetBundle assetBundle;

		internal static GameObject uiPrefab;

		internal static GameObject handlerPrefab;

		internal static GameObject impostorHandler;

		internal static GameObject crewmateHandler;

		internal static GameObject bitePrefab;

		internal static List<GameObject> networkPrefabs = new List<GameObject>();

		internal static void Init()
		{
			assetBundle = AssetBundle.LoadFromFile(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "amogus"));
			uiPrefab = TryLoadAsset<GameObject>("AmogusCanvas.prefab");
			handlerPrefab = TryLoadAsset<GameObject>("AmogusHandler.prefab");
			impostorHandler = TryLoadAsset<GameObject>("ImpostorHandler.prefab");
			crewmateHandler = TryLoadAsset<GameObject>("CrewmateHandler.prefab");
			bitePrefab = TryLoadAsset<GameObject>("BitePrefab.prefab");
		}

		private static T TryLoadAsset<T>(string name) where T : Object
		{
			AmogusPlugin.logger.LogDebug((object)("-- Loading asset: '" + name + "'"));
			T val = assetBundle.LoadAsset<T>(name);
			if ((Object)(object)val == (Object)null)
			{
				AmogusPlugin.logger.LogError((object)("FAILED TO FIND ASSET: " + name));
				return default(T);
			}
			NetworkObject val2 = default(NetworkObject);
			if (val is GameObject && ((GameObject)/*isinst with value type is only supported in some contexts*/).TryGetComponent<NetworkObject>(ref val2))
			{
				List<GameObject> list = networkPrefabs;
				object obj = val;
				list.Add((GameObject)((obj is GameObject) ? obj : null));
			}
			return val;
		}
	}
	internal static class ExtensionMethods
	{
		internal static BaseRole GetRole(this PlayerControllerB player)
		{
			foreach (BaseRole givenRole in AmogusHandler.instance.givenRoles)
			{
				if ((Object)(object)givenRole.player == (Object)(object)player)
				{
					return givenRole;
				}
			}
			return null;
		}

		public static void Shuffle<T>(this IList<T> list)
		{
			Random random = new Random(Random.Range(int.MinValue, int.MaxValue));
			int num = list.Count;
			while (num > 1)
			{
				num--;
				int index = random.Next(num + 1);
				T value = list[index];
				list[index] = list[num];
				list[num] = value;
			}
		}

		public static List<PlayerControllerB> GetConnectedPlayers(this StartOfRound startOfRound)
		{
			List<PlayerControllerB> list = new List<PlayerControllerB>();
			PlayerControllerB[] allPlayerScripts = startOfRound.allPlayerScripts;
			foreach (PlayerControllerB val in allPlayerScripts)
			{
				if (val.isPlayerControlled)
				{
					list.Add(val);
				}
			}
			return list;
		}
	}
	internal static class PlayerGetter
	{
		public static PlayerControllerB FromClientID(ulong clientId)
		{
			return StartOfRound.Instance.allPlayerScripts[StartOfRound.Instance.ClientPlayerList[clientId]];
		}
	}
}
namespace Amogus.Roles
{
	public class CrewmateRole : BaseRole
	{
		public override RoleInfo GetRoleInfo()
		{
			return AmogusPlugin.Crewmate;
		}

		public override string GetDescription()
		{
			return "Complete " + AmogusConfig.QUOTAS_TILL_CREWMATE_WIN + " quotas, without being killed by the impostors.";
		}

		protected override void __initializeVariables()
		{
			base.__initializeVariables();
		}

		protected internal override string __getTypeName()
		{
			return "CrewmateRole";
		}
	}
	public class ImpostorRole : BaseRole
	{
		[SerializeField]
		private float BiteCooldown = 1f;

		private float timeFromLastBite;

		public override RoleInfo GetRoleInfo()
		{
			return AmogusPlugin.Impostor;
		}

		public override string GetDescription()
		{
			return "Prevent the crew from completing " + AmogusConfig.QUOTAS_TILL_CREWMATE_WIN + " quotas.";
		}

		[ServerRpc]
		private void ImpostorBiteServerRpc(ulong clientId)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Invalid comparison between Unknown and I4
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Invalid comparison between Unknown and I4
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)((NetworkBehaviour)this).__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost))
			{
				if (((NetworkBehaviour)this).OwnerClientId != networkManager.LocalClientId)
				{
					if ((int)networkManager.LogLevel <= 1)
					{
						Debug.LogError((object)"Only the owner can invoke a ServerRpc that requires ownership!");
					}
					return;
				}
				ServerRpcParams val = default(ServerRpcParams);
				FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendServerRpc(2755365689u, val, (RpcDelivery)0);
				BytePacker.WriteValueBitPacked(val2, clientId);
				((NetworkBehaviour)this).__endSendServerRpc(ref val2, 2755365689u, val, (RpcDelivery)0);
			}
			if ((int)((NetworkBehaviour)this).__rpc_exec_stage == 1 && (networkManager.IsServer || networkManager.IsHost))
			{
				Object.Instantiate<GameObject>(Assets.bitePrefab).GetComponent<NetworkObject>().SpawnWithOwnership(clientId, false);
			}
		}

		private void Update()
		{
			if (((NetworkBehaviour)this).IsOwner)
			{
				timeFromLastBite += Time.deltaTime;
				if (((ButtonControl)Keyboard.current.zKey).wasPressedThisFrame && timeFromLastBite >= BiteCooldown)
				{
					timeFromLastBite = 0f;
					ImpostorBiteServerRpc(((NetworkBehaviour)this).NetworkManager.LocalClientId);
				}
			}
		}

		protected override void __initializeVariables()
		{
			base.__initializeVariables();
		}

		[RuntimeInitializeOnLoadMethod]
		internal static void InitializeRPCS_ImpostorRole()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			NetworkManager.__rpc_func_table.Add(2755365689u, new RpcReceiveHandler(__rpc_handler_2755365689));
		}

		private static void __rpc_handler_2755365689(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: 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_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Invalid comparison between Unknown and I4
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if (rpcParams.Server.Receive.SenderClientId != target.OwnerClientId)
			{
				if ((int)networkManager.LogLevel <= 1)
				{
					Debug.LogError((object)"Only the owner can invoke a ServerRpc that requires ownership!");
				}
			}
			else
			{
				ulong clientId = default(ulong);
				ByteUnpacker.ReadValueBitPacked(reader, ref clientId);
				target.__rpc_exec_stage = (__RpcExecStage)1;
				((ImpostorRole)(object)target).ImpostorBiteServerRpc(clientId);
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		protected internal override string __getTypeName()
		{
			return "ImpostorRole";
		}
	}
}
namespace Amogus.Patches
{
	[HarmonyPatch(typeof(GameNetworkManager))]
	internal static class GameNetwokManagerPatch
	{
		[HarmonyPrefix]
		[HarmonyPatch("Start")]
		internal static void RegisterPrefabs()
		{
			foreach (GameObject networkPrefab in Assets.networkPrefabs)
			{
				NetworkManager.Singleton.AddNetworkPrefab(networkPrefab);
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch("Disconnect")]
		internal static void ResetThings()
		{
			try
			{
				PlayerControllerPatch.PermDeadPlayers.Clear();
				if ((Object)(object)AmogusHandler.instance != (Object)null)
				{
					AmogusHandler.instance.HandleGameOver();
					if (((NetworkBehaviour)AmogusHandler.instance).IsOwner)
					{
						((NetworkBehaviour)AmogusHandler.instance).NetworkObject.Despawn(true);
					}
				}
			}
			catch (Exception ex)
			{
				AmogusPlugin.logger.LogError((object)ex);
			}
		}
	}
	[HarmonyPatch(typeof(HUDManager))]
	internal static class HUDManagerPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch("Start")]
		internal static void CreateCustomUI(HUDManager __instance)
		{
			Object.Instantiate<GameObject>(Assets.uiPrefab);
		}

		[HarmonyPrefix]
		[HarmonyPatch("HideHUD")]
		private static bool HideHUDPatch(bool hide)
		{
			if (GameNetworkManager.Instance.localPlayerController.isPlayerDead && !hide)
			{
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(PlayerControllerB))]
	public static class PlayerControllerPatch
	{
		internal static List<PlayerControllerB> PermDeadPlayers = new List<PlayerControllerB>();

		[HarmonyPostfix]
		[HarmonyPatch("DamagePlayerFromOtherClientClientRpc")]
		internal static void CheckIfPlayerIsDeadTillNextQuota(PlayerControllerB __instance)
		{
			try
			{
				AmogusPlugin.logger.LogDebug((object)"Handling friendly fire damage...");
				if ((Object)(object)__instance == (Object)null)
				{
					AmogusPlugin.logger.LogWarning((object)"Could not access victim after death!");
				}
				else if (__instance.isPlayerDead)
				{
					PermDeadPlayers.Add(__instance);
					if ((Object)(object)__instance == (Object)(object)GameNetworkManager.Instance.localPlayerController)
					{
						StartOfRound.Instance.SetSpectateCameraToGameOverMode(true, (PlayerControllerB)null);
						__instance.SetSpectatedPlayerEffects(false);
					}
				}
			}
			catch (Exception ex)
			{
				AmogusPlugin.logger.LogError((object)("failed to find if player killed otherplayer: " + ex));
				AmogusPlugin.logger.LogError((object)ex.StackTrace);
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch("SpectateNextPlayer")]
		private static bool DisallowSpectatingOtherPlayersWhenDead(PlayerControllerB __instance)
		{
			return PermDeadPlayers.Contains(__instance);
		}
	}
	[HarmonyPatch(typeof(StartMatchLever))]
	internal static class StartMatchLevelPatches
	{
		[HarmonyPostfix]
		[HarmonyPatch("Update")]
		internal static void Update(StartMatchLever __instance)
		{
			if (!__instance.leverHasBeenPulled || !StartOfRound.Instance.shipHasLanded)
			{
				return;
			}
			bool flag = true;
			foreach (PlayerControllerB connectedPlayer in StartOfRound.Instance.GetConnectedPlayers())
			{
				if (!connectedPlayer.isPlayerDead && !connectedPlayer.isInElevator)
				{
					flag = false;
					break;
				}
			}
			if (!flag)
			{
				__instance.triggerScript.disabledHoverTip = "[Gather all alive players]";
			}
			else
			{
				__instance.triggerScript.disabledHoverTip = "[Wait for ship to land]";
			}
			__instance.triggerScript.interactable = flag;
		}

		[HarmonyPostfix]
		[HarmonyPatch("StartGame")]
		internal static void AssignRoles(StartMatchLever __instance)
		{
			if (((NetworkBehaviour)StartOfRound.Instance).IsHost)
			{
				AmogusHandler.instance.AssignRoles();
			}
		}
	}
	[HarmonyPatch(typeof(StartOfRound))]
	internal static class StartOfRoundPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch("Start")]
		internal static void CreateAmogusHandler()
		{
			if (((NetworkBehaviour)StartOfRound.Instance).IsHost)
			{
				Object.Instantiate<GameObject>(Assets.handlerPrefab).GetComponent<NetworkObject>().Spawn(false);
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch("ReviveDeadPlayers")]
		internal static bool ohgodono(StartOfRound __instance)
		{
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			AmogusPlugin.logger.LogInfo((object)"pluh");
			__instance.allPlayersDead = false;
			for (int i = 0; i < __instance.allPlayerScripts.Length; i++)
			{
				Debug.Log((object)"Reviving players A");
				__instance.allPlayerScripts[i].ResetPlayerBloodObjects(__instance.allPlayerScripts[i].isPlayerDead);
				if (!__instance.allPlayerScripts[i].isPlayerDead && !__instance.allPlayerScripts[i].isPlayerControlled)
				{
					continue;
				}
				__instance.allPlayerScripts[i].isClimbingLadder = false;
				__instance.allPlayerScripts[i].ResetZAndXRotation();
				((Collider)__instance.allPlayerScripts[i].thisController).enabled = true;
				__instance.allPlayerScripts[i].health = 100;
				__instance.allPlayerScripts[i].disableLookInput = false;
				Debug.Log((object)"Reviving players B");
				if (__instance.allPlayerScripts[i].isPlayerDead && !PlayerControllerPatch.PermDeadPlayers.Contains(__instance.allPlayerScripts[i]))
				{
					__instance.allPlayerScripts[i].isPlayerDead = false;
					__instance.allPlayerScripts[i].isPlayerControlled = true;
					__instance.allPlayerScripts[i].isInElevator = true;
					__instance.allPlayerScripts[i].isInHangarShipRoom = true;
					__instance.allPlayerScripts[i].isInsideFactory = false;
					__instance.allPlayerScripts[i].wasInElevatorLastFrame = false;
					__instance.SetPlayerObjectExtrapolate(false);
					__instance.allPlayerScripts[i].TeleportPlayer(__instance.GetPlayerSpawnPosition(i, false), false, 0f, false, true);
					__instance.allPlayerScripts[i].setPositionOfDeadPlayer = false;
					__instance.allPlayerScripts[i].DisablePlayerModel(__instance.allPlayerObjects[i], true, true);
					((Behaviour)__instance.allPlayerScripts[i].helmetLight).enabled = false;
					Debug.Log((object)"Reviving players C");
					__instance.allPlayerScripts[i].Crouch(false);
					__instance.allPlayerScripts[i].criticallyInjured = false;
					if ((Object)(object)__instance.allPlayerScripts[i].playerBodyAnimator != (Object)null)
					{
						__instance.allPlayerScripts[i].playerBodyAnimator.SetBool("Limp", false);
					}
					__instance.allPlayerScripts[i].bleedingHeavily = false;
					__instance.allPlayerScripts[i].activatingItem = false;
					__instance.allPlayerScripts[i].twoHanded = false;
					__instance.allPlayerScripts[i].inSpecialInteractAnimation = false;
					__instance.allPlayerScripts[i].disableSyncInAnimation = false;
					__instance.allPlayerScripts[i].inAnimationWithEnemy = null;
					__instance.allPlayerScripts[i].holdingWalkieTalkie = false;
					__instance.allPlayerScripts[i].speakingToWalkieTalkie = false;
					Debug.Log((object)"Reviving players D");
					__instance.allPlayerScripts[i].isSinking = false;
					__instance.allPlayerScripts[i].isUnderwater = false;
					__instance.allPlayerScripts[i].sinkingValue = 0f;
					__instance.allPlayerScripts[i].statusEffectAudio.Stop();
					__instance.allPlayerScripts[i].DisableJetpackControlsLocally();
					__instance.allPlayerScripts[i].health = 100;
					Debug.Log((object)"Reviving players E");
					__instance.allPlayerScripts[i].mapRadarDotAnimator.SetBool("dead", false);
					if (((NetworkBehaviour)__instance.allPlayerScripts[i]).IsOwner)
					{
						HUDManager.Instance.gasHelmetAnimator.SetBool("gasEmitting", false);
						__instance.allPlayerScripts[i].hasBegunSpectating = false;
						HUDManager.Instance.RemoveSpectateUI();
						HUDManager.Instance.gameOverAnimator.SetTrigger("revive");
						__instance.allPlayerScripts[i].hinderedMultiplier = 1f;
						__instance.allPlayerScripts[i].isMovementHindered = 0;
						__instance.allPlayerScripts[i].sourcesCausingSinking = 0;
						Debug.Log((object)"Reviving players E2");
						__instance.allPlayerScripts[i].reverbPreset = __instance.shipReverb;
					}
				}
				Debug.Log((object)"Reviving players F");
				SoundManager.Instance.earsRingingTimer = 0f;
				__instance.allPlayerScripts[i].voiceMuffledByEnemy = false;
				SoundManager.Instance.playerVoicePitchTargets[i] = 1f;
				SoundManager.Instance.SetPlayerPitch(1f, i);
				if ((Object)(object)__instance.allPlayerScripts[i].currentVoiceChatIngameSettings == (Object)null)
				{
					__instance.RefreshPlayerVoicePlaybackObjects();
				}
				if ((Object)(object)__instance.allPlayerScripts[i].currentVoiceChatIngameSettings != (Object)null)
				{
					if ((Object)(object)__instance.allPlayerScripts[i].currentVoiceChatIngameSettings.voiceAudio == (Object)null)
					{
						__instance.allPlayerScripts[i].currentVoiceChatIngameSettings.InitializeComponents();
					}
					if ((Object)(object)__instance.allPlayerScripts[i].currentVoiceChatIngameSettings.voiceAudio == (Object)null)
					{
						return false;
					}
					((Component)__instance.allPlayerScripts[i].currentVoiceChatIngameSettings.voiceAudio).GetComponent<OccludeAudio>().overridingLowPass = false;
				}
				Debug.Log((object)"Reviving players G");
			}
			PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController;
			localPlayerController.bleedingHeavily = false;
			localPlayerController.criticallyInjured = false;
			localPlayerController.playerBodyAnimator.SetBool("Limp", false);
			localPlayerController.health = 100;
			HUDManager.Instance.UpdateHealthUI(100, false);
			localPlayerController.spectatedPlayerScript = null;
			((Behaviour)HUDManager.Instance.audioListenerLowPass).enabled = false;
			Debug.Log((object)"Reviving players H");
			__instance.SetSpectateCameraToGameOverMode(false, localPlayerController);
			RagdollGrabbableObject[] array = Object.FindObjectsOfType<RagdollGrabbableObject>();
			for (int j = 0; j < array.Length; j++)
			{
				if (!((GrabbableObject)array[j]).isHeld)
				{
					if (((NetworkBehaviour)__instance).IsServer)
					{
						if (((NetworkBehaviour)array[j]).NetworkObject.IsSpawned)
						{
							((NetworkBehaviour)array[j]).NetworkObject.Despawn(true);
						}
						else
						{
							Object.Destroy((Object)(object)((Component)array[j]).gameObject);
						}
					}
				}
				else if (((GrabbableObject)array[j]).isHeld && (Object)(object)((GrabbableObject)array[j]).playerHeldBy != (Object)null)
				{
					((GrabbableObject)array[j]).playerHeldBy.DropAllHeldItems(true, false);
				}
			}
			DeadBodyInfo[] array2 = Object.FindObjectsOfType<DeadBodyInfo>();
			for (int k = 0; k < array2.Length; k++)
			{
				Object.Destroy((Object)(object)((Component)array2[k]).gameObject);
			}
			__instance.livingPlayers = __instance.connectedPlayersAmount + 1;
			__instance.allPlayersDead = false;
			__instance.UpdatePlayerVoiceEffects();
			__instance.ResetMiscValues();
			return false;
		}

		[HarmonyPrefix]
		[HarmonyPatch("FirePlayersAfterDeadlineClientRpc")]
		internal static void ResetThings()
		{
			PlayerControllerPatch.PermDeadPlayers.Clear();
			AmogusHandler.instance.HandleGameOver();
		}

		[HarmonyPrefix]
		[HarmonyPatch("PassTimeToNextDay")]
		internal static void HandleNextDay()
		{
			foreach (BaseRole givenRole in AmogusHandler.instance.givenRoles)
			{
				givenRole.OnDayFinished();
			}
			foreach (Affiliation uniqueAffiliation in AmogusHandler.instance.uniqueAffiliations)
			{
				uniqueAffiliation.OnDayFinished();
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch("SwitchCamera")]
		private static void CheckIfPlayerCanSpectateOthers(StartOfRound __instance, Camera newCamera)
		{
			if ((Object)(object)newCamera == (Object)(object)__instance.spectateCamera && !PlayerControllerPatch.PermDeadPlayers.Contains(GameNetworkManager.Instance.localPlayerController))
			{
				StartOfRound.Instance.SetSpectateCameraToGameOverMode(true, (PlayerControllerB)null);
			}
		}
	}
	[HarmonyPatch(typeof(TimeOfDay))]
	internal static class TimeOfDayPatch
	{
		[HarmonyPrefix]
		[HarmonyPatch("SetNewProfitQuota")]
		internal static void WeekFinish()
		{
			foreach (BaseRole givenRole in AmogusHandler.instance.givenRoles)
			{
				givenRole.OnQuotaFufilled();
			}
			foreach (Affiliation uniqueAffiliation in AmogusHandler.instance.uniqueAffiliations)
			{
				uniqueAffiliation.OnQuotaFufilled();
			}
		}
	}
}
namespace Amogus.Behaviours
{
	public class AmogusHandler : NetworkBehaviour
	{
		internal static AmogusHandler instance;

		internal List<BaseRole> givenRoles = new List<BaseRole>();

		internal List<Affiliation> uniqueAffiliations = new List<Affiliation>();

		internal static bool gameStarted;

		private void Awake()
		{
			if (((NetworkBehaviour)StartOfRound.Instance).IsHost)
			{
				if ((Object)(object)instance != (Object)null)
				{
					AmogusPlugin.logger.LogInfo((object)"instance of amogus handler already exists");
					((NetworkBehaviour)this).NetworkObject.Despawn(true);
					Object.Destroy((Object)(object)((Component)this).gameObject);
				}
				else
				{
					AmogusPlugin.logger.LogInfo((object)"Created AmogusHandler");
					instance = this;
					Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
				}
			}
		}

		public override void OnNetworkSpawn()
		{
			if ((Object)(object)instance == (Object)null)
			{
				instance = this;
			}
		}

		private void OnDisable()
		{
			if ((Object)(object)instance == (Object)(object)this)
			{
				instance = null;
				HandleGameOver();
			}
		}

		internal void QuotaFinished()
		{
			foreach (BaseRole givenRole in givenRoles)
			{
				givenRole.OnQuotaFufilled();
			}
		}

		[ClientRpc]
		internal void AffiliationWinsClientRpc(string winning)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Invalid comparison between Unknown and I4
			//IL_005f: 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_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: 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_00ba: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost))
			{
				ClientRpcParams val = default(ClientRpcParams);
				FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(2873218868u, val, (RpcDelivery)0);
				bool flag = winning != null;
				((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag, default(ForPrimitives));
				if (flag)
				{
					((FastBufferWriter)(ref val2)).WriteValueSafe(winning, false);
				}
				((NetworkBehaviour)this).__endSendClientRpc(ref val2, 2873218868u, val, (RpcDelivery)0);
			}
			if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost))
			{
				AmogusUI.instance.GameOver(AmogusAPI.GetRoleInfoFromName(winning));
				HandleGameOver();
			}
		}

		private static List<RoleInfo> GetRandomizedRoles(List<RoleInfo> inputRoles, int numberOfPlayers)
		{
			inputRoles.Shuffle();
			List<RoleInfo> list = new List<RoleInfo>();
			foreach (Affiliation affiliation in inputRoles.Select((RoleInfo role) => role.Affiliation).Distinct().ToList())
			{
				RoleInfo roleInfo = inputRoles.FirstOrDefault((RoleInfo role) => role.Affiliation == affiliation);
				if (roleInfo.Affiliation.Required && roleInfo != null)
				{
					list.Add(roleInfo);
					roleInfo.Players++;
					numberOfPlayers--;
				}
			}
			while (numberOfPlayers > 0)
			{
				RoleInfo roleInfo2 = inputRoles[Random.Range(0, inputRoles.Count)];
				if (roleInfo2.Players < roleInfo2.MaxPlayers)
				{
					list.Add(roleInfo2);
					roleInfo2.Players++;
					numberOfPlayers--;
				}
			}
			return list;
		}

		internal void AssignRoles()
		{
			if (gameStarted)
			{
				return;
			}
			gameStarted = true;
			if (!((NetworkBehaviour)StartOfRound.Instance).IsHost)
			{
				return;
			}
			List<PlayerControllerB> connectedPlayers = StartOfRound.Instance.GetConnectedPlayers();
			List<RoleInfo> randomizedRoles = GetRandomizedRoles(AmogusAPI.Roles.ToList(), connectedPlayers.Count);
			randomizedRoles.Shuffle();
			connectedPlayers.Shuffle();
			for (int i = 0; i < connectedPlayers.Count; i++)
			{
				PlayerControllerB val = connectedPlayers[i];
				RoleInfo roleInfo = randomizedRoles[i];
				if (!uniqueAffiliations.Contains(roleInfo.Affiliation))
				{
					uniqueAffiliations.Add(roleInfo.Affiliation);
				}
				GameObject obj = Object.Instantiate<GameObject>(roleInfo.Prefab);
				obj.GetComponent<NetworkObject>().SpawnWithOwnership(val.actualClientId, false);
				obj.GetComponent<BaseRole>().player = val;
			}
		}

		internal void HandleGameOver()
		{
			foreach (BaseRole givenRole in givenRoles)
			{
				((NetworkBehaviour)givenRole).NetworkObject.Despawn(true);
			}
			givenRoles.Clear();
			uniqueAffiliations.Clear();
			gameStarted = false;
		}

		protected override void __initializeVariables()
		{
			((NetworkBehaviour)this).__initializeVariables();
		}

		[RuntimeInitializeOnLoadMethod]
		internal static void InitializeRPCS_AmogusHandler()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			NetworkManager.__rpc_func_table.Add(2873218868u, new RpcReceiveHandler(__rpc_handler_2873218868));
		}

		private static void __rpc_handler_2873218868(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: 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_007b: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				bool flag = default(bool);
				((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref flag, default(ForPrimitives));
				string winning = null;
				if (flag)
				{
					((FastBufferReader)(ref reader)).ReadValueSafe(ref winning, false);
				}
				target.__rpc_exec_stage = (__RpcExecStage)2;
				((AmogusHandler)(object)target).AffiliationWinsClientRpc(winning);
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		protected internal override string __getTypeName()
		{
			return "AmogusHandler";
		}
	}
	public class AmogusUI : MonoBehaviour
	{
		[HideInInspector]
		internal static AmogusUI instance;

		[SerializeField]
		private GameObject RoleReveal;

		private void Awake()
		{
			instance = this;
		}

		internal void RevealRole(RoleInfo role)
		{
			((MonoBehaviour)this).StartCoroutine(RevealRoleDelayed(role, 5));
		}

		internal void GameOver(RoleInfo winning)
		{
			((MonoBehaviour)this).StartCoroutine(GameOverDelayed(winning, 5));
		}

		private IEnumerator RevealRoleDelayed(RoleInfo role, int delay)
		{
			yield return (object)new WaitForSeconds((float)delay);
			GameObject obj = Object.Instantiate<GameObject>(RoleReveal);
			obj.transform.SetParent(((Component)this).transform, false);
			((Graphic)((Component)obj.transform.Find("Background")).GetComponent<Image>()).color = role.Affiliation.Color;
			((TMP_Text)((Component)obj.transform.Find("Text")).GetComponent<TextMeshProUGUI>()).text = role.Name;
			obj.GetComponent<Animator>().SetTrigger("Play");
		}

		private IEnumerator GameOverDelayed(RoleInfo winningRole, int delay)
		{
			StartOfRound.Instance.firingPlayersCutsceneRunning = true;
			if (Object.FindObjectOfType<Terminal>().terminalInUse)
			{
				Object.FindObjectOfType<Terminal>().QuitTerminal();
			}
			StartOfRound.Instance.firedVoiceSFX = null;
			((MonoBehaviour)this).StartCoroutine(StartOfRound.Instance.playersFiredGameOver(false));
			yield return (object)new WaitForSeconds((float)delay);
			PlayerControllerPatch.PermDeadPlayers.Clear();
			AmogusHandler.instance.HandleGameOver();
			((TMP_Text)HUDManager.Instance.EndOfRunStatsText).text = winningRole.Name + " win!";
			StartOfRound.Instance.gameStats.daysSpent = 0;
			StartOfRound.Instance.gameStats.scrapValueCollected = 0;
			StartOfRound.Instance.gameStats.deaths = 0;
			StartOfRound.Instance.gameStats.allStepsTaken = 0;
			StartOfRound.Instance.SetDiscordStatusDetails();
		}
	}
	public class BiteAttack : NetworkBehaviour
	{
		[SerializeField]
		private int Damage = 25;

		private bool localPlayerIsInside;

		[HideInInspector]
		public PlayerControllerB player { get; internal set; }

		public override void OnNetworkSpawn()
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: 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_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			player = PlayerGetter.FromClientID(((NetworkBehaviour)this).OwnerClientId);
			((Component)this).transform.position = player.cameraContainerTransform.position + player.cameraContainerTransform.forward - Vector3.up * 0.4f;
			((Component)this).transform.eulerAngles = new Vector3(-90f + Random.Range(-10f, 10f), 90f, -90f + ((Component)player).transform.eulerAngles.y);
		}

		public void Bite()
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			if (localPlayerIsInside && !player.GetRole().roleInfo.Affiliation.Friendly(GameNetworkManager.Instance.localPlayerController.GetRole().roleInfo.Affiliation))
			{
				GameNetworkManager.Instance.localPlayerController.DamagePlayerFromOtherClientServerRpc(Damage, Vector3.zero, (int)player.playerClientId);
			}
			((Component)this).GetComponent<AudioSource>().Play();
		}

		public void Dispose()
		{
			if (((NetworkBehaviour)this).IsHost || ((NetworkBehaviour)this).IsServer)
			{
				((NetworkBehaviour)this).NetworkObject.Despawn(true);
			}
		}

		private void OnTriggerEnter(Collider other)
		{
			PlayerControllerB val = default(PlayerControllerB);
			if (((Object)((Component)other).gameObject).name == "PlayerPhysicsBox" && ((Component)((Component)other).transform.parent).TryGetComponent<PlayerControllerB>(ref val) && (Object)(object)GameNetworkManager.Instance.localPlayerController == (Object)(object)val)
			{
				localPlayerIsInside = true;
			}
		}

		private void OnTriggerExit(Collider other)
		{
			PlayerControllerB val = default(PlayerControllerB);
			if (((Object)((Component)other).gameObject).name == "PlayerPhysicsBox" && ((Component)((Component)other).transform.parent).TryGetComponent<PlayerControllerB>(ref val) && (Object)(object)GameNetworkManager.Instance.localPlayerController == (Object)(object)val)
			{
				localPlayerIsInside = false;
			}
		}

		protected override void __initializeVariables()
		{
			((NetworkBehaviour)this).__initializeVariables();
		}

		protected internal override string __getTypeName()
		{
			return "BiteAttack";
		}
	}
	public class DestroyFunctionBehaviour : MonoBehaviour
	{
		public void DestroyMe()
		{
			Object.Destroy((Object)(object)((Component)this).gameObject);
		}
	}
}
namespace Amogus.API
{
	public abstract class Affiliation
	{
		public string Name { get; private set; }

		public Color Color { get; private set; }

		internal bool Required { get; private set; }

		public Affiliation(string name, Color color)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			Name = name;
			Color = color;
			Required = true;
		}

		public virtual bool Friendly(Affiliation other)
		{
			return other == this;
		}

		public virtual void OnRoundStart()
		{
		}

		public virtual void OnRoundEnd()
		{
		}

		public virtual void OnQuotaFufilled()
		{
		}

		public virtual void OnDayFinished()
		{
		}

		protected void Win()
		{
			AmogusPlugin.logger.LogInfo((object)(Name + " wins!"));
			if (((NetworkBehaviour)StartOfRound.Instance).IsHost)
			{
				AmogusHandler.instance.AffiliationWinsClientRpc(Name);
			}
		}
	}
	public static class AmogusAPI
	{
		public static Affiliation Impostor = new ImpostorSide();

		public static Affiliation Crewmate = new CrewmateSide();

		private static readonly Dictionary<string, RoleInfo> roles = new Dictionary<string, RoleInfo>();

		public static IReadOnlyCollection<RoleInfo> Roles => roles.Values;

		public static void RegisterRole(RoleInfo role)
		{
			roles[role.Name] = role;
			AmogusPlugin.logger.LogInfo((object)("Registered new role: " + role.Name));
		}

		public static RoleInfo GetRoleInfoFromName(string name)
		{
			return roles[name];
		}
	}
	public abstract class BaseRole : NetworkBehaviour
	{
		public string Name => roleInfo.Name;

		public RoleInfo roleInfo => GetRoleInfo();

		public PlayerControllerB player { get; internal set; }

		public abstract RoleInfo GetRoleInfo();

		public override void OnNetworkSpawn()
		{
			player = PlayerGetter.FromClientID(((NetworkBehaviour)this).OwnerClientId);
			AmogusHandler.instance.givenRoles.Add(this);
			OnRoundStart();
			if ((Object)(object)player == (Object)(object)GameNetworkManager.Instance.localPlayerController)
			{
				AmogusUI.instance.RevealRole(roleInfo);
				HUDManager.Instance.AddChatMessage(Name + ":\n" + GetDescription(), "");
			}
		}

		public override void OnNetworkDespawn()
		{
			OnRoundEnd();
		}

		public virtual void OnRoundStart()
		{
		}

		public virtual void OnRoundEnd()
		{
		}

		public virtual void OnQuotaFufilled()
		{
		}

		public virtual void OnDayFinished()
		{
		}

		public virtual string GetDescription()
		{
			return Name + "hasn't provided a proper description!";
		}

		protected override void __initializeVariables()
		{
			((NetworkBehaviour)this).__initializeVariables();
		}

		protected internal override string __getTypeName()
		{
			return "BaseRole";
		}
	}
	public class RoleInfo
	{
		public string Name { get; set; }

		public int MinPlayers { get; set; } = 1;


		public int MaxPlayers { get; set; }

		public int Players { get; internal set; }

		public Affiliation Affiliation { get; }

		internal GameObject Prefab { get; }

		public RoleInfo(Affiliation affiliation, GameObject prefab)
		{
			Affiliation = affiliation;
			Prefab = prefab;
			base..ctor();
		}
	}
}
namespace Amogus.Affiliations
{
	public class CrewmateSide : Affiliation
	{
		internal int quotasTillCrewmateVictory;

		public CrewmateSide()
			: base("Crewmate", new Color(0f, 0.9f, 1f))
		{
		}//IL_0015: Unknown result type (might be due to invalid IL or missing references)


		public override void OnDayFinished()
		{
			foreach (PlayerControllerB connectedPlayer in StartOfRound.Instance.GetConnectedPlayers())
			{
				if (!connectedPlayer.isPlayerDead && !connectedPlayer.GetRole().roleInfo.Affiliation.Friendly(this))
				{
					return;
				}
			}
			Win();
		}

		public override void OnRoundStart()
		{
			quotasTillCrewmateVictory = AmogusConfig.QUOTAS_TILL_CREWMATE_WIN;
		}

		public override void OnQuotaFufilled()
		{
			quotasTillCrewmateVictory--;
			HUDManager.Instance.AddChatMessage($"There are {quotasTillCrewmateVictory} more quota(s) untill Crewmate Victory!", "");
			if (quotasTillCrewmateVictory <= 0)
			{
				Win();
			}
		}
	}
	public class ImpostorSide : Affiliation
	{
		public ImpostorSide()
			: base("Impostor", new Color(1f, 0f, 0f))
		{
		}//IL_0015: Unknown result type (might be due to invalid IL or missing references)


		public override void OnDayFinished()
		{
			foreach (PlayerControllerB connectedPlayer in StartOfRound.Instance.GetConnectedPlayers())
			{
				if (!connectedPlayer.isPlayerDead && !connectedPlayer.GetRole().roleInfo.Affiliation.Friendly(this))
				{
					return;
				}
			}
			Win();
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}
namespace Amogus.NetcodePatcher
{
	[AttributeUsage(AttributeTargets.Module)]
	internal class NetcodePatchedAssemblyAttribute : Attribute
	{
	}
}