Decompiled source of Schizo v1.1.0

Schizo.dll

Decompiled 2 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using TMPro;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.AI;

[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: CompilationRelaxations(8)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace Schizo;

internal static class Affliction
{
	private const string AssignMessage = "Schizo.Assign";

	private const string SlotsMessage = "Schizo.Slots";

	private const ulong Nobody = ulong.MaxValue;

	internal static ulong AfflictedClientId = ulong.MaxValue;

	private static readonly Dictionary<ulong, int> phantomSlotMasks = new Dictionary<ulong, int>();

	private static CustomMessagingManager registeredWith;

	internal static bool LocalPlayerIsAfflicted
	{
		get
		{
			PlayerControllerB localPlayer = LocalPlayer;
			if ((Object)(object)localPlayer != (Object)null && AfflictedClientId != ulong.MaxValue)
			{
				return localPlayer.actualClientId == AfflictedClientId;
			}
			return false;
		}
	}

	internal static PlayerControllerB LocalPlayer
	{
		get
		{
			if (!((Object)(object)GameNetworkManager.Instance != (Object)null))
			{
				return null;
			}
			return GameNetworkManager.Instance.localPlayerController;
		}
	}

	internal static void OnLobbyStarted()
	{
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Expected O, but got Unknown
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Expected O, but got Unknown
		AfflictedClientId = ulong.MaxValue;
		phantomSlotMasks.Clear();
		NetworkManager singleton = NetworkManager.Singleton;
		if (!((Object)(object)singleton == (Object)null) && singleton.CustomMessagingManager != null && singleton.CustomMessagingManager != registeredWith)
		{
			registeredWith = singleton.CustomMessagingManager;
			registeredWith.RegisterNamedMessageHandler("Schizo.Assign", new HandleNamedMessageDelegate(OnAssignReceived));
			registeredWith.RegisterNamedMessageHandler("Schizo.Slots", new HandleNamedMessageDelegate(OnSlotsReceived));
		}
	}

	internal static void OnLobbyEnded()
	{
		if (registeredWith != null)
		{
			try
			{
				registeredWith.UnregisterNamedMessageHandler("Schizo.Assign");
				registeredWith.UnregisterNamedMessageHandler("Schizo.Slots");
			}
			catch (Exception)
			{
			}
			registeredWith = null;
		}
		AfflictedClientId = ulong.MaxValue;
		phantomSlotMasks.Clear();
	}

	internal static void OnRoundEnded()
	{
		phantomSlotMasks.Clear();
	}

	internal static void HostAssignForRound()
	{
		NetworkManager singleton = NetworkManager.Singleton;
		if ((Object)(object)singleton == (Object)null || !singleton.IsServer)
		{
			return;
		}
		if (AfflictedClientId == ulong.MaxValue || Plugin.RerollEachRound.Value || (Object)(object)FindPlayer(AfflictedClientId) == (Object)null)
		{
			List<PlayerControllerB> list = new List<PlayerControllerB>();
			PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
			foreach (PlayerControllerB val in allPlayerScripts)
			{
				if ((Object)(object)val != (Object)null && val.isPlayerControlled && !val.isPlayerDead)
				{
					list.Add(val);
				}
			}
			if (list.Count == 0)
			{
				return;
			}
			AfflictedClientId = list[Random.Range(0, list.Count)].actualClientId;
		}
		byte[] bytes = BitConverter.GetBytes(AfflictedClientId);
		foreach (ulong connectedClientsId in singleton.ConnectedClientsIds)
		{
			if (connectedClientsId != singleton.LocalClientId)
			{
				Send("Schizo.Assign", connectedClientsId, bytes);
			}
		}
		ApplyAssignment(AfflictedClientId);
	}

	private static void OnAssignReceived(ulong senderClientId, FastBufferReader reader)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		if (senderClientId == 0)
		{
			byte[] array = Read(reader, 8);
			if (array != null)
			{
				ApplyAssignment(BitConverter.ToUInt64(array, 0));
			}
		}
	}

	private static void ApplyAssignment(ulong clientId)
	{
		AfflictedClientId = clientId;
		if (LocalPlayerIsAfflicted)
		{
			Phantoms.SpawnForRound();
			if (Plugin.TellAfflictedPlayer.Value && (Object)(object)HUDManager.Instance != (Object)null)
			{
				HUDManager.Instance.DisplayTip("Something is wrong", "Not everything you see in there is real.", true, false, "LC_Tip1");
			}
		}
	}

	internal static void BroadcastLocalPhantomSlots(int mask)
	{
		NetworkManager singleton = NetworkManager.Singleton;
		if (!((Object)(object)singleton == (Object)null) && singleton.IsListening)
		{
			if (singleton.IsServer)
			{
				Relay(singleton, singleton.LocalClientId, mask, singleton.LocalClientId);
			}
			else
			{
				Send("Schizo.Slots", 0uL, BitConverter.GetBytes(mask));
			}
		}
	}

	private static void OnSlotsReceived(ulong senderClientId, FastBufferReader reader)
	{
		//IL_0018: 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)
		NetworkManager singleton = NetworkManager.Singleton;
		if ((Object)(object)singleton == (Object)null)
		{
			return;
		}
		if (singleton.IsServer)
		{
			byte[] array = Read(reader, 4);
			if (array != null)
			{
				int num = BitConverter.ToInt32(array, 0);
				phantomSlotMasks[senderClientId] = num;
				Relay(singleton, senderClientId, num, senderClientId);
			}
		}
		else if (senderClientId == 0)
		{
			byte[] array2 = Read(reader, 12);
			if (array2 != null)
			{
				phantomSlotMasks[BitConverter.ToUInt64(array2, 0)] = BitConverter.ToInt32(array2, 8);
			}
		}
	}

	private static void Relay(NetworkManager network, ulong owner, int mask, ulong skip)
	{
		byte[] array = new byte[12];
		Buffer.BlockCopy(BitConverter.GetBytes(owner), 0, array, 0, 8);
		Buffer.BlockCopy(BitConverter.GetBytes(mask), 0, array, 8, 4);
		foreach (ulong connectedClientsId in network.ConnectedClientsIds)
		{
			if (connectedClientsId != network.LocalClientId && connectedClientsId != skip)
			{
				Send("Schizo.Slots", connectedClientsId, array);
			}
		}
	}

	internal static int PhantomSlotMaskOf(PlayerControllerB player)
	{
		if ((Object)(object)player == (Object)(object)LocalPlayer || !phantomSlotMasks.TryGetValue(player.actualClientId, out var value))
		{
			return 0;
		}
		return value;
	}

	private static PlayerControllerB FindPlayer(ulong clientId)
	{
		PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
		foreach (PlayerControllerB val in allPlayerScripts)
		{
			if ((Object)(object)val != (Object)null && val.isPlayerControlled && val.actualClientId == clientId)
			{
				return val;
			}
		}
		return null;
	}

	private static void Send(string message, ulong clientId, byte[] payload)
	{
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		FastBufferWriter val = default(FastBufferWriter);
		((FastBufferWriter)(ref val))..ctor(payload.Length, (Allocator)2, -1);
		try
		{
			((FastBufferWriter)(ref val)).WriteBytesSafe(payload, payload.Length, 0);
			NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage(message, clientId, val, (NetworkDelivery)3);
		}
		finally
		{
			((FastBufferWriter)(ref val)).Dispose();
		}
	}

	private static byte[] Read(FastBufferReader reader, int size)
	{
		if (((FastBufferReader)(ref reader)).Length - ((FastBufferReader)(ref reader)).Position < size)
		{
			return null;
		}
		byte[] result = new byte[size];
		((FastBufferReader)(ref reader)).ReadBytesSafe(ref result, size, 0);
		return result;
	}
}
internal static class Monsters
{
	private static readonly HashSet<string> allowedAITypes = new HashSet<string> { "CrawlerAI", "FlowermanAI", "HoarderBugAI", "SandSpiderAI", "SpringManAI", "NutcrackerEnemyAI", "ButlerEnemyAI", "PufferAI", "JesterAI" };

	private static readonly List<PhantomMonster> alive = new List<PhantomMonster>();

	private static float nextSpawnTime = -1f;

	internal static void Tick(PlayerControllerB player)
	{
		StartOfRound instance = StartOfRound.Instance;
		if (!Plugin.MonsterHallucinations.Value || (Object)(object)instance == (Object)null || instance.inShipPhase || !instance.shipHasLanded || !player.isInsideFactory || player.isPlayerDead)
		{
			nextSpawnTime = -1f;
		}
		else if (nextSpawnTime < 0f)
		{
			nextSpawnTime = Time.time + NextInterval();
		}
		else if (!(Time.time < nextSpawnTime))
		{
			alive.RemoveAll((PhantomMonster monster) => (Object)(object)monster == (Object)null);
			if (alive.Count < Plugin.MaxMonstersAtOnce.Value)
			{
				nextSpawnTime = Time.time + (TrySpawn(player) ? NextInterval() : 5f);
			}
		}
	}

	private static float NextInterval()
	{
		float num = Mathf.Max(5f, Plugin.MonsterIntervalMin.Value);
		return Random.Range(num, Mathf.Max(num, Plugin.MonsterIntervalMax.Value));
	}

	private static bool TrySpawn(PlayerControllerB player)
	{
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		if (!FindHiddenSpawn(player, out var position))
		{
			return false;
		}
		List<EnemyType> list = EnemyPool();
		if (list.Count == 0)
		{
			return false;
		}
		EnemyType enemy = list[Random.Range(0, list.Count)];
		PhantomMonster phantomMonster = Build(enemy, position);
		if ((Object)(object)phantomMonster == (Object)null)
		{
			return false;
		}
		phantomMonster.Begin(player);
		alive.Add(phantomMonster);
		return true;
	}

	private static bool FindHiddenSpawn(PlayerControllerB player, out Vector3 position)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: 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_0081: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0101: 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_00a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
		position = Vector3.zero;
		GameObject[] array = (((Object)(object)RoundManager.Instance != (Object)null) ? RoundManager.Instance.insideAINodes : null);
		if (array == null || array.Length == 0)
		{
			return false;
		}
		Vector3 position2 = ((Component)player.gameplayCamera).transform.position;
		int collidersAndRoomMaskAndDefault = StartOfRound.Instance.collidersAndRoomMaskAndDefault;
		List<Vector3> list = new List<Vector3>();
		GameObject[] array2 = array;
		NavMeshHit val2 = default(NavMeshHit);
		foreach (GameObject val in array2)
		{
			if (!((Object)(object)val == (Object)null))
			{
				Vector3 position3 = val.transform.position;
				float num = Vector3.Distance(position3, ((Component)player).transform.position);
				if (!(num < 14f) && !(num > 40f) && Physics.Linecast(position2, position3 + Vector3.up, collidersAndRoomMaskAndDefault, (QueryTriggerInteraction)1) && NavMesh.SamplePosition(position3, ref val2, 2f, -1))
				{
					list.Add(((NavMeshHit)(ref val2)).position);
				}
			}
		}
		if (list.Count == 0)
		{
			return false;
		}
		position = list[Random.Range(0, list.Count)];
		return true;
	}

	private static List<EnemyType> EnemyPool()
	{
		List<EnemyType> list = new List<EnemyType>();
		StartOfRound instance = StartOfRound.Instance;
		AddAllowed(instance.currentLevel, list);
		if (list.Count == 0 && instance.levels != null)
		{
			SelectableLevel[] levels = instance.levels;
			foreach (SelectableLevel level in levels)
			{
				AddAllowed(level, list);
			}
		}
		return list;
	}

	private static void AddAllowed(SelectableLevel level, List<EnemyType> pool)
	{
		if ((Object)(object)level == (Object)null || level.Enemies == null)
		{
			return;
		}
		foreach (SpawnableEnemyWithRarity enemy in level.Enemies)
		{
			if (enemy != null && !((Object)(object)enemy.enemyType == (Object)null) && !((Object)(object)enemy.enemyType.enemyPrefab == (Object)null) && !pool.Contains(enemy.enemyType))
			{
				EnemyAI componentInChildren = enemy.enemyType.enemyPrefab.GetComponentInChildren<EnemyAI>(true);
				if ((Object)(object)componentInChildren != (Object)null && allowedAITypes.Contains(((object)componentInChildren).GetType().Name))
				{
					pool.Add(enemy.enemyType);
				}
			}
		}
	}

	private static PhantomMonster Build(EnemyType enemy, Vector3 position)
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Expected O, but got Unknown
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject("SchizoMonsterHolder");
		val.SetActive(false);
		try
		{
			GameObject val2 = Object.Instantiate<GameObject>(enemy.enemyPrefab, val.transform);
			((Object)val2).name = "Hallucination (" + enemy.enemyName + ")";
			EnemyAI componentInChildren = val2.GetComponentInChildren<EnemyAI>(true);
			bool freezes = componentInChildren is SpringManAI;
			List<AudioClip> harvested = HarvestSounds(componentInChildren);
			Strip(val2);
			val2.transform.position = position;
			val2.transform.rotation = Quaternion.Euler(0f, Random.Range(0f, 360f), 0f);
			PhantomMonster phantomMonster = val2.AddComponent<PhantomMonster>();
			phantomMonster.Configure(harvested, freezes);
			val2.transform.SetParent((Transform)null, true);
			return phantomMonster;
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("Couldn't build a hallucination from " + enemy.enemyName + ": " + ex.Message));
			return null;
		}
		finally
		{
			Object.Destroy((Object)(object)val);
		}
	}

	private static List<AudioClip> HarvestSounds(EnemyAI ai)
	{
		List<AudioClip> list = new List<AudioClip>();
		if ((Object)(object)ai == (Object)null)
		{
			return list;
		}
		Type type = ((object)ai).GetType();
		while (type != null && type != typeof(MonoBehaviour))
		{
			FieldInfo[] fields = type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (FieldInfo fieldInfo in fields)
			{
				if (fieldInfo.FieldType == typeof(AudioClip))
				{
					object? value = fieldInfo.GetValue(ai);
					AudioClip val = (AudioClip)((value is AudioClip) ? value : null);
					if ((Object)(object)val != (Object)null && !list.Contains(val))
					{
						list.Add(val);
					}
				}
				else
				{
					if (!(fieldInfo.FieldType == typeof(AudioClip[])) || !(fieldInfo.GetValue(ai) is AudioClip[] array))
					{
						continue;
					}
					AudioClip[] array2 = array;
					foreach (AudioClip val2 in array2)
					{
						if ((Object)(object)val2 != (Object)null && !list.Contains(val2))
						{
							list.Add(val2);
						}
					}
				}
			}
			type = type.BaseType;
		}
		return list;
	}

	private static void Strip(GameObject body)
	{
		int num = int.MaxValue;
		for (int i = 0; i < 5; i++)
		{
			List<MonoBehaviour> list = new List<MonoBehaviour>();
			MonoBehaviour[] componentsInChildren = body.GetComponentsInChildren<MonoBehaviour>(true);
			foreach (MonoBehaviour val in componentsInChildren)
			{
				if ((Object)(object)val != (Object)null && !(val is ScanNodeProperties))
				{
					list.Add(val);
				}
			}
			if (list.Count == 0 || list.Count >= num)
			{
				break;
			}
			num = list.Count;
			foreach (MonoBehaviour item in list)
			{
				Object.DestroyImmediate((Object)(object)item);
			}
		}
		Collider[] componentsInChildren2 = body.GetComponentsInChildren<Collider>(true);
		foreach (Collider val2 in componentsInChildren2)
		{
			if ((Object)(object)((Component)val2).GetComponent<ScanNodeProperties>() == (Object)null)
			{
				Object.DestroyImmediate((Object)(object)val2);
			}
		}
		Rigidbody[] componentsInChildren3 = body.GetComponentsInChildren<Rigidbody>(true);
		foreach (Rigidbody val3 in componentsInChildren3)
		{
			val3.isKinematic = true;
		}
		ScanNodeProperties[] componentsInChildren4 = body.GetComponentsInChildren<ScanNodeProperties>(true);
		foreach (ScanNodeProperties val4 in componentsInChildren4)
		{
			val4.creatureScanID = -1;
		}
		Animator[] componentsInChildren5 = body.GetComponentsInChildren<Animator>(true);
		foreach (Animator val5 in componentsInChildren5)
		{
			val5.fireEvents = false;
			val5.applyRootMotion = false;
		}
	}

	internal static void DestroyAll()
	{
		foreach (PhantomMonster item in alive)
		{
			if ((Object)(object)item != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)item).gameObject);
			}
		}
		alive.Clear();
		nextSpawnTime = -1f;
	}
}
internal class PhantomMonster : MonoBehaviour
{
	private const float WalkSpeed = 3.5f;

	private const float ChaseSpeed = 6.5f;

	private const float ChaseRange = 18f;

	private const float LungeRange = 1.4f;

	private PlayerControllerB target;

	private NavMeshAgent agent;

	private Animator[] animators;

	private readonly List<KeyValuePair<Animator, int>> speedFloats = new List<KeyValuePair<Animator, int>>();

	private readonly List<KeyValuePair<Animator, int>> movingBools = new List<KeyValuePair<Animator, int>>();

	private AudioSource voice;

	private List<AudioClip> sounds;

	private bool freezesWhenSeen;

	private float lifetime;

	private float nextPath;

	private float nextSound;

	private bool vanishing;

	internal void Configure(List<AudioClip> harvested, bool freezes)
	{
		sounds = harvested;
		freezesWhenSeen = freezes;
	}

	internal void Begin(PlayerControllerB player)
	{
		//IL_0098: Unknown result type (might be due to invalid IL or missing references)
		target = player;
		lifetime = Random.Range(25f, 45f);
		nextSound = Time.time + Random.Range(1f, 4f);
		animators = ((Component)this).GetComponentsInChildren<Animator>();
		FindMovementParameters();
		voice = ((Component)this).GetComponentInChildren<AudioSource>();
		agent = ((Component)this).GetComponent<NavMeshAgent>();
		if ((Object)(object)agent == (Object)null)
		{
			agent = ((Component)this).gameObject.AddComponent<NavMeshAgent>();
		}
		((Behaviour)agent).enabled = true;
		agent.Warp(((Component)this).transform.position);
		agent.speed = 3.5f;
		agent.acceleration = 12f;
		agent.angularSpeed = 300f;
		agent.stoppingDistance = 0f;
		agent.autoBraking = false;
	}

	private void Update()
	{
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_011b: Unknown result type (might be due to invalid IL or missing references)
		if (vanishing)
		{
			return;
		}
		if ((Object)(object)target == (Object)null || target.isPlayerDead || !target.isInsideFactory)
		{
			Object.Destroy((Object)(object)((Component)this).gameObject);
			return;
		}
		lifetime -= Time.deltaTime;
		if (lifetime <= 0f)
		{
			Object.Destroy((Object)(object)((Component)this).gameObject);
			return;
		}
		float num = Vector3.Distance(((Component)this).transform.position, ((Component)target).transform.position);
		if (num < 1.4f)
		{
			Lunge();
			return;
		}
		bool flag = PlayerCanSee();
		bool flag2 = freezesWhenSeen && flag;
		if (agent.isOnNavMesh)
		{
			agent.isStopped = flag2;
			agent.speed = ((num < 18f && HasLineOfSight()) ? 6.5f : 3.5f);
			if (Time.time >= nextPath)
			{
				nextPath = Time.time + 0.25f;
				agent.SetDestination(((Component)target).transform.position);
			}
		}
		Animate(flag2);
		if (!flag2 && Time.time >= nextSound)
		{
			nextSound = Time.time + Random.Range(3f, 8f);
			PlayRandomSound(0.8f);
		}
	}

	private void FindMovementParameters()
	{
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Invalid comparison between Unknown and I4
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		//IL_0089: Invalid comparison between Unknown and I4
		Animator[] array = animators;
		foreach (Animator val in array)
		{
			if ((Object)(object)val == (Object)null || (Object)(object)val.runtimeAnimatorController == (Object)null)
			{
				continue;
			}
			AnimatorControllerParameter[] parameters = val.parameters;
			foreach (AnimatorControllerParameter val2 in parameters)
			{
				string text = val2.name.ToLowerInvariant();
				if ((int)val2.type == 1 && text.Contains("speed"))
				{
					speedFloats.Add(new KeyValuePair<Animator, int>(val, val2.nameHash));
				}
				else if ((int)val2.type == 4 && (text.Contains("walk") || text.Contains("moving") || text.Contains("run")))
				{
					movingBools.Add(new KeyValuePair<Animator, int>(val, val2.nameHash));
				}
			}
		}
	}

	private void Animate(bool frozen)
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		float num;
		if (!((Object)(object)agent != (Object)null))
		{
			num = 0f;
		}
		else
		{
			Vector3 velocity = agent.velocity;
			num = ((Vector3)(ref velocity)).magnitude;
		}
		float num2 = num;
		Animator[] array = animators;
		foreach (Animator val in array)
		{
			if ((Object)(object)val != (Object)null)
			{
				val.speed = (frozen ? 0f : 1f);
			}
		}
		foreach (KeyValuePair<Animator, int> speedFloat in speedFloats)
		{
			speedFloat.Key.SetFloat(speedFloat.Value, Mathf.Clamp(num2 / 3.5f, 0f, 2f));
		}
		foreach (KeyValuePair<Animator, int> movingBool in movingBools)
		{
			movingBool.Key.SetBool(movingBool.Value, num2 > 0.2f);
		}
	}

	private void Lunge()
	{
		vanishing = true;
		PlayRandomSound(1f);
		target.JumpToFearLevel(1f, true);
		if ((Object)(object)HUDManager.Instance != (Object)null)
		{
			HUDManager.Instance.ShakeCamera((ScreenShakeType)1);
		}
		Renderer[] componentsInChildren = ((Component)this).GetComponentsInChildren<Renderer>();
		foreach (Renderer val in componentsInChildren)
		{
			val.enabled = false;
		}
		ScanNodeProperties[] componentsInChildren2 = ((Component)this).GetComponentsInChildren<ScanNodeProperties>();
		foreach (ScanNodeProperties val2 in componentsInChildren2)
		{
			((Component)val2).gameObject.SetActive(false);
		}
		if ((Object)(object)agent != (Object)null)
		{
			((Behaviour)agent).enabled = false;
		}
		Object.Destroy((Object)(object)((Component)this).gameObject, 3f);
	}

	private void PlayRandomSound(float volume)
	{
		if (!((Object)(object)voice == (Object)null) && sounds != null && sounds.Count != 0)
		{
			voice.PlayOneShot(sounds[Random.Range(0, sounds.Count)], volume);
		}
	}

	private bool PlayerCanSee()
	{
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//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: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//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)
		Transform transform = ((Component)target.gameplayCamera).transform;
		Vector3 val = ((Component)this).transform.position + Vector3.up - transform.position;
		if (Vector3.Angle(transform.forward, val) < 40f)
		{
			return HasLineOfSight();
		}
		return false;
	}

	private bool HasLineOfSight()
	{
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: 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)
		return !Physics.Linecast(((Component)target.gameplayCamera).transform.position, ((Component)this).transform.position + Vector3.up, StartOfRound.Instance.collidersAndRoomMaskAndDefault, (QueryTriggerInteraction)1);
	}
}
[HarmonyPatch(typeof(StartOfRound))]
internal static class StartOfRoundPatches
{
	[HarmonyPostfix]
	[HarmonyPatch("Start")]
	private static void LobbyStarted()
	{
		Affliction.OnLobbyStarted();
	}

	[HarmonyPatch("OnDestroy")]
	[HarmonyPrefix]
	private static void LobbyEnded()
	{
		Phantoms.OnRoundEnded();
		Monsters.DestroyAll();
		Affliction.OnLobbyEnded();
	}

	[HarmonyPostfix]
	[HarmonyPatch("OnShipLandedMiscEvents")]
	private static void ShipLanded()
	{
		Affliction.HostAssignForRound();
	}

	[HarmonyPostfix]
	[HarmonyPatch("ShipLeave")]
	private static void ShipLeft()
	{
		Phantoms.OnRoundEnded();
		Monsters.DestroyAll();
		Affliction.OnRoundEnded();
	}
}
[HarmonyPatch(typeof(RoundManager), "DespawnPropsAtEndOfRound")]
internal static class DespawnPropsPatch
{
	private static void Prefix()
	{
		Phantoms.OnRoundEnded();
	}
}
[HarmonyPatch(typeof(PlayerControllerB))]
internal static class PlayerPatches
{
	[HarmonyPrefix]
	[HarmonyPatch("BeginGrabObject")]
	private static bool BeginGrabObject(PlayerControllerB __instance)
	{
		if (!Phantoms.AnyExist || (Object)(object)__instance != (Object)(object)Affliction.LocalPlayer)
		{
			return true;
		}
		GrabbableObject val = Phantoms.PhantomUnderCursor(__instance);
		if ((Object)(object)val == (Object)null)
		{
			return true;
		}
		Phantoms.BeginGrab(__instance, val);
		return false;
	}

	[HarmonyPrefix]
	[HarmonyPatch("DiscardHeldObject")]
	private static bool DiscardHeldObject(PlayerControllerB __instance)
	{
		if (!((NetworkBehaviour)__instance).IsOwner || !Phantoms.IsPhantom(__instance.currentlyHeldObjectServer))
		{
			return true;
		}
		if (!__instance.isGrabbingObjectAnimation)
		{
			Phantoms.Drop(__instance, __instance.currentlyHeldObjectServer);
		}
		return false;
	}

	[HarmonyPrefix]
	[HarmonyPatch("DropAllHeldItems")]
	private static void DropAllHeldItems(PlayerControllerB __instance)
	{
		if (Phantoms.AnyExist && (Object)(object)__instance == (Object)(object)Affliction.LocalPlayer)
		{
			Phantoms.VanishFromInventory(__instance);
		}
	}

	[HarmonyPatch("Update")]
	[HarmonyPostfix]
	private static void Update(PlayerControllerB __instance)
	{
		if (((NetworkBehaviour)__instance).IsOwner && Affliction.LocalPlayerIsAfflicted && (Object)(object)__instance == (Object)(object)Affliction.LocalPlayer)
		{
			Monsters.Tick(__instance);
		}
		if (Phantoms.AnyExist && (!__instance.isInsideFactory || __instance.isPlayerDead) && (Object)(object)__instance == (Object)(object)Affliction.LocalPlayer && Phantoms.HasPhantomInInventory(__instance))
		{
			Phantoms.VanishFromInventory(__instance);
		}
	}

	[HarmonyPatch("FirstEmptyItemSlot")]
	[HarmonyPrefix]
	private static bool FirstEmptyItemSlot(PlayerControllerB __instance, GrabbableObject attemptingGrab, ref int __result)
	{
		int num = Affliction.PhantomSlotMaskOf(__instance);
		if (num == 0)
		{
			return true;
		}
		if ((Object)(object)__instance.ItemOnlySlot == (Object)null && (Object)(object)attemptingGrab != (Object)null && !attemptingGrab.itemProperties.isScrap && !attemptingGrab.itemProperties.twoHanded && !attemptingGrab.itemProperties.disallowUtilitySlot)
		{
			__result = 50;
			return false;
		}
		int currentItemSlot = __instance.currentItemSlot;
		if (currentItemSlot != 50 && currentItemSlot < __instance.ItemSlots.Length && IsFree(__instance, currentItemSlot, num))
		{
			__result = currentItemSlot;
			return false;
		}
		__result = -1;
		for (int i = 0; i < __instance.ItemSlots.Length; i++)
		{
			if (IsFree(__instance, i, num))
			{
				__result = i;
				break;
			}
		}
		return false;
	}

	private static bool IsFree(PlayerControllerB player, int slot, int phantomSlots)
	{
		if ((Object)(object)player.ItemSlots[slot] == (Object)null)
		{
			if (slot < 32)
			{
				return (phantomSlots & (1 << slot)) == 0;
			}
			return true;
		}
		return false;
	}
}
[HarmonyPatch(typeof(GrabbableObject))]
internal static class GrabbableObjectPatches
{
	[HarmonyPatch("Start")]
	[HarmonyPostfix]
	private static void Start(GrabbableObject __instance)
	{
		if (Phantoms.IsPhantom(__instance))
		{
			HoarderBugAI.grabbableObjectsInMap.Remove(((Component)__instance).gameObject);
		}
	}

	[HarmonyPrefix]
	[HarmonyPatch("UseItemOnClient")]
	private static bool UseItemOnClient(GrabbableObject __instance)
	{
		return !Phantoms.IsPhantom(__instance);
	}

	[HarmonyPatch("ItemInteractLeftRightOnClient")]
	[HarmonyPrefix]
	private static bool ItemInteractLeftRightOnClient(GrabbableObject __instance)
	{
		return !Phantoms.IsPhantom(__instance);
	}
}
[HarmonyPatch(typeof(HoarderBugAI), "RefreshGrabbableObjectsInMapList")]
internal static class HoarderBugRefreshPatch
{
	private static void Postfix()
	{
		HoarderBugAI.grabbableObjectsInMap.RemoveAll((GameObject item) => (Object)(object)item != (Object)null && (Object)(object)item.GetComponent<PhantomItem>() != (Object)null);
	}
}
internal class PhantomItem : MonoBehaviour
{
}
internal static class Phantoms
{
	private static readonly List<GrabbableObject> spawned = new List<GrabbableObject>();

	private static int spawnedForSeed = int.MinValue;

	private static readonly FieldInfo interactableObjectsMask = AccessTools.Field(typeof(PlayerControllerB), "interactableObjectsMask");

	private static readonly FieldInfo throwingObject = AccessTools.Field(typeof(PlayerControllerB), "throwingObject");

	private static readonly MethodInfo firstEmptyItemSlot = AccessTools.Method(typeof(PlayerControllerB), "FirstEmptyItemSlot", (Type[])null, (Type[])null);

	private static readonly MethodInfo switchToItemSlot = AccessTools.Method(typeof(PlayerControllerB), "SwitchToItemSlot", (Type[])null, (Type[])null);

	private static readonly MethodInfo switchToSlotServerRpc = AccessTools.Method(typeof(PlayerControllerB), "SwitchToSlotServerRpc", (Type[])null, (Type[])null);

	private static readonly MethodInfo setSpecialGrabAnimationBool = AccessTools.Method(typeof(PlayerControllerB), "SetSpecialGrabAnimationBool", (Type[])null, (Type[])null);

	internal static bool AnyExist => spawned.Count > 0;

	internal static bool IsPhantom(GrabbableObject item)
	{
		if ((Object)(object)item != (Object)null)
		{
			return (Object)(object)((Component)item).GetComponent<PhantomItem>() != (Object)null;
		}
		return false;
	}

	internal static void SpawnForRound()
	{
		//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_0103: Unknown result type (might be due to invalid IL or missing references)
		//IL_0115: Unknown result type (might be due to invalid IL or missing references)
		//IL_0130: Unknown result type (might be due to invalid IL or missing references)
		StartOfRound instance = StartOfRound.Instance;
		if ((Object)(object)instance == (Object)null || (Object)(object)RoundManager.Instance == (Object)null || (Object)(object)instance.currentLevel == (Object)null || !instance.currentLevel.spawnEnemiesAndScrap || spawnedForSeed == instance.randomMapSeed)
		{
			return;
		}
		DestroyAll();
		spawnedForSeed = instance.randomMapSeed;
		List<SpawnableItemWithRarity> list = new List<SpawnableItemWithRarity>();
		int num = 0;
		foreach (SpawnableItemWithRarity item in instance.currentLevel.spawnableScrap)
		{
			if (item != null && item.rarity > 0 && IsPlainScrap(item.spawnableItem))
			{
				list.Add(item);
				num += item.rarity;
			}
		}
		List<Vector3> list2 = PickSpawnPositions(Plugin.PhantomCount.Value);
		if (list.Count == 0 || list2.Count == 0)
		{
			Plugin.Log.LogWarning((object)"No usable scrap types or spawn points on this moon, so no phantoms this round.");
			return;
		}
		foreach (Vector3 item2 in list2)
		{
			Item val = PickWeighted(list, num);
			GameObject val2 = Object.Instantiate<GameObject>(val.spawnPrefab, item2, Quaternion.Euler(0f, Random.Range(0f, 360f), 0f));
			NetworkObject component = val2.GetComponent<NetworkObject>();
			if ((Object)(object)component != (Object)null)
			{
				component.AutoObjectParentSync = false;
			}
			val2.transform.SetParent(instance.propsContainer, true);
			val2.AddComponent<PhantomItem>();
			GrabbableObject component2 = val2.GetComponent<GrabbableObject>();
			component2.isInFactory = true;
			component2.grabbableToEnemies = false;
			component2.hasBeenHeld = true;
			float num2 = (float)Random.Range(val.minValue, val.maxValue) * RoundManager.Instance.scrapValueMultiplier;
			component2.SetScrapValue(Mathf.Max(1, (int)num2));
			spawned.Add(component2);
		}
	}

	private static bool IsPlainScrap(Item item)
	{
		if ((Object)(object)item == (Object)null || !item.isScrap || (Object)(object)item.spawnPrefab == (Object)null)
		{
			return false;
		}
		GrabbableObject component = item.spawnPrefab.GetComponent<GrabbableObject>();
		if ((Object)(object)component != (Object)null)
		{
			return ((object)component).GetType() == typeof(PhysicsProp);
		}
		return false;
	}

	private static Item PickWeighted(List<SpawnableItemWithRarity> pool, int totalRarity)
	{
		int num = Random.Range(0, totalRarity);
		foreach (SpawnableItemWithRarity item in pool)
		{
			num -= item.rarity;
			if (num < 0)
			{
				return item.spawnableItem;
			}
		}
		return pool[pool.Count - 1].spawnableItem;
	}

	private static List<Vector3> PickSpawnPositions(int count)
	{
		//IL_001f: 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_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0080: Unknown result type (might be due to invalid IL or missing references)
		//IL_00da: 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)
		//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_00a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d2: 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_0165: Unknown result type (might be due to invalid IL or missing references)
		//IL_016a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0174: Unknown result type (might be due to invalid IL or missing references)
		//IL_0179: Unknown result type (might be due to invalid IL or missing references)
		//IL_0131: Unknown result type (might be due to invalid IL or missing references)
		List<Vector3> list = new List<Vector3>();
		GrabbableObject[] array = Object.FindObjectsOfType<GrabbableObject>();
		foreach (GrabbableObject val in array)
		{
			list.Add(((Component)val).transform.position);
		}
		List<Vector3> list2 = new List<Vector3>();
		RandomScrapSpawn[] array2 = Object.FindObjectsOfType<RandomScrapSpawn>();
		NavMeshHit val4 = default(NavMeshHit);
		foreach (RandomScrapSpawn val2 in array2)
		{
			if (val2.spawnUsed || IsNearAny(((Component)val2).transform.position, list, 1.5f))
			{
				continue;
			}
			Vector3 position = ((Component)val2).transform.position;
			if (val2.itemSpawnRange > 0f)
			{
				Vector2 val3 = Random.insideUnitCircle * val2.itemSpawnRange;
				if (NavMesh.SamplePosition(position + new Vector3(val3.x, 0f, val3.y), ref val4, val2.itemSpawnRange, -1))
				{
					position = ((NavMeshHit)(ref val4)).position;
				}
			}
			list2.Add(position);
		}
		if (list2.Count < count && RoundManager.Instance.insideAINodes != null)
		{
			GameObject[] insideAINodes = RoundManager.Instance.insideAINodes;
			foreach (GameObject val5 in insideAINodes)
			{
				if ((Object)(object)val5 != (Object)null)
				{
					list2.Add(val5.transform.position);
				}
			}
		}
		List<Vector3> list3 = new List<Vector3>();
		while (list3.Count < count && list2.Count > 0)
		{
			int index = Random.Range(0, list2.Count);
			list3.Add(list2[index] + Vector3.up * 0.5f);
			list2.RemoveAt(index);
		}
		return list3;
	}

	private static bool IsNearAny(Vector3 position, List<Vector3> others, float distance)
	{
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		foreach (Vector3 other in others)
		{
			Vector3 val = other - position;
			if (((Vector3)(ref val)).sqrMagnitude < distance * distance)
			{
				return true;
			}
		}
		return false;
	}

	internal static GrabbableObject PhantomUnderCursor(PlayerControllerB player)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		Ray val = default(Ray);
		((Ray)(ref val))..ctor(((Component)player.gameplayCamera).transform.position, ((Component)player.gameplayCamera).transform.forward);
		RaycastHit val2 = default(RaycastHit);
		if (!Physics.Raycast(val, ref val2, player.grabDistance, (int)interactableObjectsMask.GetValue(player)))
		{
			return null;
		}
		if (((Component)((RaycastHit)(ref val2)).collider).gameObject.layer == 8 || !((Component)((RaycastHit)(ref val2)).collider).CompareTag("PhysicsProp"))
		{
			return null;
		}
		GrabbableObject component = ((Component)((Component)((RaycastHit)(ref val2)).collider).transform).gameObject.GetComponent<GrabbableObject>();
		if (!IsPhantom(component))
		{
			return null;
		}
		return component;
	}

	internal static void BeginGrab(PlayerControllerB player, GrabbableObject item)
	{
		if (!player.twoHanded && !(player.sinkingValue > 0.73f) && !player.inSpecialInteractAnimation && !item.isHeld && !item.isPocketed)
		{
			int num = (int)firstEmptyItemSlot.Invoke(player, new object[1] { item });
			if (num != -1 && num != 50)
			{
				player.playerBodyAnimator.SetBool("GrabInvalidated", false);
				player.playerBodyAnimator.SetBool("GrabValidated", false);
				player.playerBodyAnimator.SetBool("cancelHolding", false);
				player.playerBodyAnimator.ResetTrigger("Throw");
				setSpecialGrabAnimationBool.Invoke(player, new object[2] { true, null });
				player.isGrabbingObjectAnimation = true;
				((Behaviour)player.cursorIcon).enabled = false;
				((TMP_Text)player.cursorTip).text = "";
				player.twoHanded = item.itemProperties.twoHanded;
				player.carryWeight = Mathf.Clamp(player.carryWeight + (item.itemProperties.weight - 1f), 1f, 10f);
				StartOfRound.Instance.SendChangedWeightEvent();
				player.grabObjectAnimationTime = ((item.itemProperties.grabAnimationTime > 0f) ? item.itemProperties.grabAnimationTime : 0.4f);
				((MonoBehaviour)player).StartCoroutine(GrabRoutine(player, item, num));
			}
		}
	}

	private static IEnumerator GrabRoutine(PlayerControllerB player, GrabbableObject item, int slot)
	{
		yield return (object)new WaitForSeconds(0.1f);
		if ((Object)(object)item == (Object)null || player.isPlayerDead || !player.isInsideFactory)
		{
			player.isGrabbingObjectAnimation = false;
			player.twoHanded = false;
			if ((Object)(object)item != (Object)null)
			{
				player.carryWeight = Mathf.Clamp(player.carryWeight - (item.itemProperties.weight - 1f), 1f, 10f);
			}
			yield break;
		}
		AudioClip[] grabSounds = StartOfRound.Instance.playerGrabSFX;
		player.itemAudio.PlayOneShot(grabSounds[Random.Range(0, grabSounds.Length)]);
		item.parentObject = player.localItemHolder;
		if ((Object)(object)item.itemProperties.grabSFX != (Object)null)
		{
			player.itemAudio.PlayOneShot(item.itemProperties.grabSFX, 1f);
		}
		int previousSlot = player.currentItemSlot;
		switchToItemSlot.Invoke(player, new object[2] { slot, item });
		item.EnablePhysics(false);
		item.isHeld = true;
		item.hasHitGround = false;
		item.isInFactory = player.isInsideFactory;
		player.twoHanded = item.itemProperties.twoHanded;
		player.twoHandedAnimation = item.itemProperties.twoHandedAnimation;
		if (slot != previousSlot)
		{
			switchToSlotServerRpc.Invoke(player, new object[1] { slot });
		}
		Affliction.BroadcastLocalPhantomSlots(SlotMask(player));
		HUDManager.Instance.ClearControlTips();
		item.SetControlTipsForItem();
		player.isHoldingObject = true;
		yield return (object)new WaitForSeconds(Mathf.Max(0f, player.grabObjectAnimationTime - 0.2f));
		player.playerBodyAnimator.SetBool("GrabValidated", true);
		player.isGrabbingObjectAnimation = false;
		if (player.queueDiscardObject)
		{
			player.queueDiscardObject = false;
			if ((Object)(object)player.currentlyHeldObjectServer == (Object)(object)item)
			{
				Drop(player, item);
			}
		}
	}

	internal static void Drop(PlayerControllerB player, GrabbableObject item)
	{
		//IL_006c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		//IL_0078: 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_0084: Unknown result type (might be due to invalid IL or missing references)
		//IL_0089: Unknown result type (might be due to invalid IL or missing references)
		//IL_008d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		setSpecialGrabAnimationBool.Invoke(player, new object[2] { false, item });
		player.playerBodyAnimator.SetBool("cancelHolding", true);
		player.playerBodyAnimator.SetTrigger("Throw");
		((Behaviour)HUDManager.Instance.itemSlotIcons[player.currentItemSlot]).enabled = false;
		((Behaviour)HUDManager.Instance.holdingTwoHandedItem).enabled = false;
		Vector3 itemFloorPosition = item.GetItemFloorPosition(default(Vector3));
		Vector3 val = StartOfRound.Instance.propsContainer.InverseTransformPoint(itemFloorPosition);
		player.SetObjectAsNoLongerHeld(false, false, val, item, (int)((Component)player).transform.localEulerAngles.y);
		item.playerHeldBy = null;
		player.currentlyHeldObjectServer = null;
		throwingObject.SetValue(player, false);
		HUDManager.Instance.ClearControlTips();
		Affliction.BroadcastLocalPhantomSlots(SlotMask(player));
	}

	internal static void VanishFromInventory(PlayerControllerB player)
	{
		bool flag = false;
		for (int i = 0; i < player.ItemSlots.Length; i++)
		{
			GrabbableObject val = player.ItemSlots[i];
			if (IsPhantom(val))
			{
				if ((Object)(object)player.currentlyHeldObjectServer == (Object)(object)val)
				{
					setSpecialGrabAnimationBool.Invoke(player, new object[2] { false, val });
					player.isHoldingObject = false;
					player.twoHanded = false;
					player.twoHandedAnimation = false;
					player.activatingItem = false;
					player.playerBodyAnimator.SetBool("cancelHolding", true);
					player.playerBodyAnimator.SetTrigger("Throw");
					((Behaviour)HUDManager.Instance.holdingTwoHandedItem).enabled = false;
					HUDManager.Instance.ClearControlTips();
					player.currentlyHeldObjectServer = null;
				}
				player.carryWeight = Mathf.Clamp(player.carryWeight - (val.itemProperties.weight - 1f), 1f, 10f);
				((Behaviour)HUDManager.Instance.itemSlotIcons[i]).enabled = false;
				player.ItemSlots[i] = null;
				spawned.Remove(val);
				Object.DestroyImmediate((Object)(object)((Component)val).gameObject);
				flag = true;
			}
		}
		if (flag)
		{
			StartOfRound.Instance.SendChangedWeightEvent();
			Affliction.BroadcastLocalPhantomSlots(0);
		}
	}

	internal static bool HasPhantomInInventory(PlayerControllerB player)
	{
		return SlotMask(player) != 0;
	}

	private static int SlotMask(PlayerControllerB player)
	{
		int num = 0;
		for (int i = 0; i < player.ItemSlots.Length && i < 32; i++)
		{
			if (IsPhantom(player.ItemSlots[i]))
			{
				num |= 1 << i;
			}
		}
		return num;
	}

	internal static void DestroyAll()
	{
		PlayerControllerB localPlayer = Affliction.LocalPlayer;
		if ((Object)(object)localPlayer != (Object)null)
		{
			VanishFromInventory(localPlayer);
		}
		foreach (GrabbableObject item in spawned)
		{
			if ((Object)(object)item != (Object)null)
			{
				Object.DestroyImmediate((Object)(object)((Component)item).gameObject);
			}
		}
		spawned.Clear();
	}

	internal static void OnRoundEnded()
	{
		DestroyAll();
		spawnedForSeed = int.MinValue;
	}
}
[BepInPlugin("axelc.schizo", "Schizo", "1.1.0")]
public class Plugin : BaseUnityPlugin
{
	public const string Guid = "axelc.schizo";

	public const string PluginName = "Schizo";

	public const string Version = "1.1.0";

	internal static ManualLogSource Log;

	internal static ConfigEntry<int> PhantomCount;

	internal static ConfigEntry<bool> RerollEachRound;

	internal static ConfigEntry<bool> TellAfflictedPlayer;

	internal static ConfigEntry<bool> MonsterHallucinations;

	internal static ConfigEntry<float> MonsterIntervalMin;

	internal static ConfigEntry<float> MonsterIntervalMax;

	internal static ConfigEntry<int> MaxMonstersAtOnce;

	private void Awake()
	{
		//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
		Log = ((BaseUnityPlugin)this).Logger;
		PhantomCount = ((BaseUnityPlugin)this).Config.Bind<int>("Hallucinations", "PhantomItemCount", 5, "How many fake scrap items the afflicted player sees in the facility each round.");
		RerollEachRound = ((BaseUnityPlugin)this).Config.Bind<bool>("Affliction", "RerollEachRound", false, "Off: one player is picked the first time the ship lands and keeps it for the whole lobby. On: a new player is picked every landing. Only the host's setting matters.");
		TellAfflictedPlayer = ((BaseUnityPlugin)this).Config.Bind<bool>("Affliction", "TellAfflictedPlayer", false, "Show the afflicted player a warning when they get it. Off by default so they don't know.");
		MonsterHallucinations = ((BaseUnityPlugin)this).Config.Bind<bool>("Monsters", "Enabled", true, "The afflicted player sees monsters in the facility that aren't there. They can't hurt anyone.");
		MonsterIntervalMin = ((BaseUnityPlugin)this).Config.Bind<float>("Monsters", "MinSecondsBetween", 45f, "Shortest wait between fake monsters while the afflicted player is inside.");
		MonsterIntervalMax = ((BaseUnityPlugin)this).Config.Bind<float>("Monsters", "MaxSecondsBetween", 120f, "Longest wait between fake monsters while the afflicted player is inside.");
		MaxMonstersAtOnce = ((BaseUnityPlugin)this).Config.Bind<int>("Monsters", "MaxAtOnce", 1, "Most fake monsters that can be around the afflicted player at the same time.");
		new Harmony("axelc.schizo").PatchAll();
		Log.LogInfo((object)"Schizo 1.1.0 loaded.");
	}
}