Decompiled source of MaliciousHeads v0.1.2

MaliciousHeads.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
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 HarmonyLib;
using MaliciousHeads.Manager;
using MaliciousHeads.Util;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using REPOLib.Modules;
using UnityEngine;

[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: AssemblyCompany("Xepos")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.2.0")]
[assembly: AssemblyInformationalVersion("0.1.2+31cda87f62f9866bf60b1a53d62b38ea166ae8a4")]
[assembly: AssemblyProduct("MaliciousHeads")]
[assembly: AssemblyTitle("MaliciousHeads")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.2.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 MaliciousHeads
{
	[BepInPlugin("Xepos.MaliciousHeads", "MaliciousHeads", "0.1.2")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class MaliciousHeads : BaseUnityPlugin
	{
		internal static MaliciousHeads Instance { get; private set; }

		internal static ManualLogSource Logger => Instance._logger;

		private ManualLogSource _logger => ((BaseUnityPlugin)this).Logger;

		internal Harmony? Harmony { get; set; }

		private void Awake()
		{
			Instance = this;
			((Component)this).gameObject.transform.parent = null;
			((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
			Settings.Initialize(((BaseUnityPlugin)this).Config);
			Patch();
			Logger.LogInfo((object)$"{((BaseUnityPlugin)this).Info.Metadata.GUID} v{((BaseUnityPlugin)this).Info.Metadata.Version} has loaded!");
		}

		internal void Patch()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			//IL_0025: Expected O, but got Unknown
			if (Harmony == null)
			{
				Harmony val = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID);
				Harmony val2 = val;
				Harmony = val;
			}
			Harmony.PatchAll();
		}

		internal void Unpatch()
		{
			Harmony? harmony = Harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
	internal class Settings
	{
		public static ConfigEntry<byte> MaxHeadSpawnsPerLevel { get; private set; }

		public static ConfigEntry<byte> SpawnChanceOnPlayeDeath { get; private set; }

		public static ConfigEntry<float> FuseTime { get; private set; }

		public static void Initialize(ConfigFile config)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Expected O, but got Unknown
			MaxHeadSpawnsPerLevel = config.Bind<byte>("Heads", "Maximum Head Spawns", (byte)2, new ConfigDescription("Maximum amount of heads that can spawn per level", (AcceptableValueBase)(object)new AcceptableValueRange<byte>((byte)0, byte.MaxValue), Array.Empty<object>()));
			SpawnChanceOnPlayeDeath = config.Bind<byte>("Heads", "Spawn Chance", (byte)50, new ConfigDescription("Percentage chance of spawning a head when a player dies", (AcceptableValueBase)(object)new AcceptableValueRange<byte>((byte)0, (byte)100), Array.Empty<object>()));
		}
	}
}
namespace MaliciousHeads.XEnemy
{
	internal class EnemyMaliciousHead : MonoBehaviour
	{
		public enum State
		{
			Spawn,
			Idle,
			Despawn
		}

		public bool debugSpawn;

		[Space]
		public State currentState;

		private bool stateImpulse;

		internal float stateTimer;

		[Space]
		public Rigidbody rigidbody;

		[Space]
		public Enemy enemy;

		public PhysGrabObject physGrabObject;

		private PhotonView photonView;

		[Space]
		public MapCustom mapCustom;

		[Space]
		public float holdThreshold = 2f;

		private float _holdStartTime;

		private bool _hasSelfDestructed;

		private bool wasHoldingLastFrame;

		private AnimationCurve eyeFlashCurve;

		public Light eyeFlashLight;

		public float eyeFlashLightIntensity;

		private Material eyeMaterial;

		private int eyeMaterialAmount;

		private int eyeMaterialColor;

		private bool eyeFlash;

		private float eyeFlashLerp;

		[Space]
		public MeshRenderer headRenderer;

		[Space]
		public MeshRenderer[] eyeRenderers;

		[Space]
		public Color eyeFlashPositiveColor;

		public Color eyeFlashNegativeColor;

		[Space]
		public Sound eyeFlashPositiveSound;

		public Sound eyeFlashNegativeSound;

		[Space]
		public AudioClip seenSound;

		private float seenCooldownTime = 2f;

		private float seenCooldownTimer;

		private bool localSeen;

		private bool localSeenEffect;

		private float localSeenEffectTime = 2f;

		private float localSeenEffectTimer;

		public bool serverSeen;

		private bool setup;

		private void Awake()
		{
			photonView = ((Component)this).GetComponent<PhotonView>();
			if (!Application.isEditor || (SemiFunc.IsMultiplayer() && !GameManager.instance.localTest))
			{
				debugSpawn = false;
			}
			MeshRenderer[] array = eyeRenderers;
			foreach (MeshRenderer val in array)
			{
				if (!Object.op_Implicit((Object)(object)eyeMaterial))
				{
					eyeMaterial = ((Renderer)val).material;
				}
				((Renderer)val).material = eyeMaterial;
			}
			eyeMaterialAmount = Shader.PropertyToID("_ColorOverlayAmount");
			eyeMaterialColor = Shader.PropertyToID("_ColorOverlay");
			eyeFlashCurve = AssetManager.instance.animationCurveImpact;
			localSeenEffectTimer = localSeenEffectTime;
		}

		private void Start()
		{
			((MonoBehaviour)this).StartCoroutine(Setup());
		}

		private void Update()
		{
			//IL_023d: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: 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_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: 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_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			if (!GameManager.Multiplayer() || PhotonNetwork.IsMasterClient)
			{
				switch (currentState)
				{
				case State.Spawn:
					StateSpawn();
					break;
				case State.Idle:
					StateIdle();
					break;
				case State.Despawn:
					StateDespawn();
					break;
				}
			}
			if (!localSeen && !PlayerController.instance.playerAvatarScript.isDisabled)
			{
				if (seenCooldownTimer > 0f)
				{
					seenCooldownTimer -= Time.deltaTime;
				}
				else
				{
					Vector3 localCameraPosition = PlayerController.instance.playerAvatarScript.localCameraPosition;
					float num = Vector3.Distance(((Component)this).transform.position, localCameraPosition);
					if (num <= 10f && SemiFunc.OnScreen(((Component)this).transform.position, -0.15f, -0.15f))
					{
						Vector3 val = localCameraPosition - ((Component)this).transform.position;
						Vector3 normalized = ((Vector3)(ref val)).normalized;
						RaycastHit val2 = default(RaycastHit);
						if (!Physics.Raycast(physGrabObject.centerPoint, normalized, ref val2, num, LayerMask.GetMask(new string[1] { "Default" })))
						{
							localSeen = true;
							TutorialDirector.instance.playerSawHead = true;
							if (!serverSeen && SemiFunc.RunIsLevel())
							{
								if (SemiFunc.IsMultiplayer())
								{
									photonView.RPC("SeenSetRPC", (RpcTarget)0, new object[1] { true });
								}
								else
								{
									SeenSetRPC(seen: true);
								}
								if (PlayerController.instance.deathSeenTimer <= 0f)
								{
									localSeenEffect = true;
									PlayerController.instance.deathSeenTimer = 30f;
									GameDirector.instance.CameraImpact.Shake(2f, 0.5f);
									GameDirector.instance.CameraShake.Shake(2f, 1f);
									AudioScare.instance.PlayCustom(seenSound, 0.3f, 60f);
									ValuableDiscover.instance.New(physGrabObject, (State)2);
								}
							}
						}
					}
				}
			}
			if (localSeenEffect)
			{
				localSeenEffectTimer -= Time.deltaTime;
				CameraZoom.Instance.OverrideZoomSet(75f, 0.1f, 0.25f, 0.25f, ((Component)this).gameObject, 150);
				PostProcessing.Instance.VignetteOverride(Color.black, 0.4f, 1f, 1f, 0.5f, 0.1f, ((Component)this).gameObject);
				PostProcessing.Instance.SaturationOverride(-50f, 1f, 0.5f, 0.1f, ((Component)this).gameObject);
				PostProcessing.Instance.ContrastOverride(5f, 1f, 0.5f, 0.1f, ((Component)this).gameObject);
				GameDirector.instance.CameraImpact.Shake(10f * Time.deltaTime, 0.1f);
				GameDirector.instance.CameraShake.Shake(10f * Time.deltaTime, 1f);
				if (localSeenEffectTimer <= 0f)
				{
					localSeenEffect = false;
				}
			}
			bool flag = false;
			foreach (PhysGrabber item in physGrabObject.playerGrabbing)
			{
				if (SemiFunc.PlayerGetSteamID(item.playerAvatar) == SemiFunc.PlayerGetSteamID(PlayerAvatar.instance))
				{
					flag = true;
					break;
				}
			}
			if (eyeFlash)
			{
				eyeFlashLerp += holdThreshold * Time.deltaTime;
				eyeFlashLerp = Mathf.Clamp01(eyeFlashLerp);
				eyeMaterial.SetFloat(eyeMaterialAmount, eyeFlashCurve.Evaluate(eyeFlashLerp));
				eyeFlashLight.intensity = eyeFlashCurve.Evaluate(eyeFlashLerp) * eyeFlashLightIntensity;
				if (eyeFlashLerp > 1f)
				{
					eyeFlash = false;
					eyeMaterial.SetFloat(eyeMaterialAmount, 0f);
					((Component)eyeFlashLight).gameObject.SetActive(false);
				}
			}
			if (flag)
			{
				if (!wasHoldingLastFrame)
				{
					_holdStartTime = Time.time;
					_hasSelfDestructed = false;
					FlashEye();
				}
				float num2 = Time.time - _holdStartTime;
				if (!_hasSelfDestructed && num2 >= holdThreshold)
				{
					FlashEye();
					ChatManager.instance.PossessSelfDestruction();
					_hasSelfDestructed = true;
				}
			}
			else
			{
				_holdStartTime = -1f;
				_hasSelfDestructed = false;
			}
			wasHoldingLastFrame = flag;
		}

		private IEnumerator Setup()
		{
			while (!LevelGenerator.Instance.Generated)
			{
				yield return (object)new WaitForSeconds(0.1f);
			}
			if (!GameManager.Multiplayer() || PhotonNetwork.IsMasterClient)
			{
				string randomPlayerSteamID = GetRandomPlayerSteamID();
				if (GameManager.Multiplayer())
				{
					photonView.RPC("SetupRPC", (RpcTarget)4, new object[1] { randomPlayerSteamID });
				}
				SetupDone(randomPlayerSteamID);
				if (SemiFunc.RunIsArena())
				{
					physGrabObject.impactDetector.destroyDisable = false;
				}
				setup = true;
			}
		}

		public void UpdateState(State _state)
		{
			if (currentState != _state)
			{
				currentState = _state;
				stateImpulse = true;
				stateTimer = 0f;
				if (GameManager.Multiplayer())
				{
					photonView.RPC("UpdateStateRPC", (RpcTarget)0, new object[1] { currentState });
				}
				else
				{
					UpdateStateRPC(currentState);
				}
			}
		}

		[PunRPC]
		public void SetupRPC(string steamID)
		{
			MaliciousHeads.Logger.LogDebug((object)("[RPC] SetupRPC called with parameter steamID: " + steamID));
			((MonoBehaviour)this).StartCoroutine(Wrap(SetupClient(steamID)));
		}

		private IEnumerator SetupClient(string steamID)
		{
			while (!Object.op_Implicit((Object)(object)physGrabObject))
			{
				MaliciousHeads.Logger.LogWarning((object)"No Phys Grab Object");
				yield return (object)new WaitForSeconds(0.1f);
			}
			while (!Object.op_Implicit((Object)(object)physGrabObject.impactDetector))
			{
				MaliciousHeads.Logger.LogWarning((object)"No Impact Detector");
				yield return (object)new WaitForSeconds(0.1f);
			}
			while (!Object.op_Implicit((Object)(object)physGrabObject.impactDetector.particles))
			{
				MaliciousHeads.Logger.LogWarning((object)"No Impact Detector Particles");
				yield return (object)new WaitForSeconds(0.1f);
			}
			MaliciousHeads.Logger.LogDebug((object)("SetupClient finished: " + steamID));
			SetupDone(steamID);
		}

		private string GetRandomPlayerSteamID()
		{
			PlayerAvatar val = GameDirector.instance.PlayerList[Random.Range(0, GameDirector.instance.PlayerList.Count)];
			return SemiFunc.PlayerGetSteamID(val);
		}

		private void SetupDone(string steamID)
		{
			if (steamID == null)
			{
				Debug.LogError((object)"Failed to set Malicious Head color");
				return;
			}
			PlayerAvatar val = SemiFunc.PlayerGetFromSteamID(steamID);
			if (steamID == null)
			{
				Debug.LogError((object)"Failed to set Malicious Head color: No player avatar");
				return;
			}
			((Renderer)headRenderer).material = val.playerHealth.bodyMaterial;
			((Renderer)headRenderer).material.SetFloat(Shader.PropertyToID("_ColorOverlayAmount"), 0f);
		}

		public void FlashEye()
		{
			if (SemiFunc.IsMultiplayer())
			{
				photonView.RPC("FlashEyeRPC", (RpcTarget)0, new object[1] { false });
			}
			FlashEyeRPC(_positive: false);
		}

		[PunRPC]
		public void FlashEyeRPC(bool _positive)
		{
			//IL_0065: 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_00a1: 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_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: 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 (_positive)
			{
				eyeMaterial.SetColor(eyeMaterialColor, eyeFlashPositiveColor);
				eyeFlashPositiveSound.Play(((Component)this).transform.position, 1f, 1f, 1f, 1f);
				eyeFlashLight.color = eyeFlashPositiveColor;
			}
			else
			{
				eyeMaterial.SetColor(eyeMaterialColor, eyeFlashNegativeColor);
				eyeFlashNegativeSound.Play(((Component)this).transform.position, 1f, 1f, 1f, 1f);
				eyeFlashLight.color = eyeFlashNegativeColor;
			}
			eyeFlash = true;
			eyeFlashLerp = 0f;
			((Component)eyeFlashLight).gameObject.SetActive(true);
			GameDirector.instance.CameraImpact.ShakeDistance(1f, 2f, 8f, ((Component)this).transform.position, 0.25f);
			GameDirector.instance.CameraShake.ShakeDistance(1f, 2f, 8f, ((Component)this).transform.position, 0.5f);
		}

		private void StateSpawn()
		{
			if (stateImpulse)
			{
				stateImpulse = false;
				stateTimer = 1f;
				ApplyVelocity();
				ApplyAngularVelocity();
				seenCooldownTimer = seenCooldownTime;
				localSeen = false;
				localSeenEffect = false;
				serverSeen = false;
			}
			stateTimer -= Time.deltaTime;
			if (stateTimer <= 0f)
			{
				UpdateState(State.Idle);
			}
		}

		private void StateIdle()
		{
			if (stateImpulse)
			{
				stateImpulse = false;
				stateTimer = 60f;
			}
			if (physGrabObject.playerGrabbing.Count == 0)
			{
				stateTimer -= Time.deltaTime;
			}
			else if (stateTimer < 2f)
			{
				stateTimer = 2f;
			}
			if (stateTimer <= 0f)
			{
				UpdateState(State.Despawn);
			}
		}

		private void StateDespawn()
		{
			if (stateImpulse)
			{
				stateImpulse = false;
				enemy.EnemyParent.Despawn();
			}
		}

		public void OnSpawn()
		{
			if (SemiFunc.IsMasterClientOrSingleplayer() && SemiFunc.EnemySpawn(enemy))
			{
				UpdateState(State.Spawn);
			}
		}

		[PunRPC]
		private void UpdateStateRPC(State _state)
		{
			currentState = _state;
			_ = currentState;
		}

		[PunRPC]
		private void SeenSetRPC(bool seen)
		{
			MaliciousHeads.Logger.LogDebug((object)$"[RPC] Setting server seen to {seen}");
			serverSeen = seen;
		}

		private static IEnumerator Wrap(IEnumerator ie)
		{
			while (true)
			{
				yield return ie.Current;
				try
				{
					ie.MoveNext();
				}
				catch (Exception ex)
				{
					MaliciousHeads.Logger.LogError((object)ex.ToString());
				}
			}
		}

		private void ApplyVelocity()
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			float num = Random.Range(-3f, 3f);
			float num2 = Random.Range(5f, 10f);
			float num3 = Random.Range(-3f, 3f);
			rigidbody.velocity = new Vector3(num, num2, num3);
		}

		private void ApplyAngularVelocity()
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			float num = Random.Range(-2f, 2f);
			float num2 = Random.Range(-2f, 2f);
			float num3 = Random.Range(-2f, 2f);
			rigidbody.angularVelocity = new Vector3(num, num2, num3);
		}
	}
	internal class MaliciousHeadMapController : MonoBehaviour
	{
		public MapCustom mapCustom;

		public GameObject enableObject;

		public EnemyMaliciousHead enemyMaliciousHead;

		public void Update()
		{
			if (!enemyMaliciousHead.serverSeen || !enableObject.activeSelf)
			{
				mapCustom.Hide();
			}
		}
	}
}
namespace MaliciousHeads.Util
{
	internal static class REPOLibUtils
	{
		internal static List<EnemyParent>? SpawnEnemyNowInVanillaManner(EnemySetup enemySetup)
		{
			//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)
			List<EnemyParent> list = Enemies.SpawnEnemy(enemySetup, Vector3.zero, Quaternion.identity, true);
			if (list != null)
			{
				foreach (EnemyParent item in list)
				{
					item.DespawnedTimer = 0f;
				}
			}
			return list;
		}
	}
}
namespace MaliciousHeads.Patch
{
	[HarmonyPatch(typeof(EnemyDirector))]
	internal class EnemyDirectorPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch("Start")]
		private static void EnemyDirectorStartPostfix()
		{
			if (SemiFunc.IsNotMasterClient() || !SemiFunc.RunIsLevel())
			{
				return;
			}
			EnemyDirector instance = EnemyDirector.instance;
			EnemyManager instance2 = EnemyManager.Instance;
			MaliciousHeads.Logger.LogDebug((object)"Level changed, setting SpawnedHeads count back to 0");
			instance2.SpawnedHeads = 0;
			IList<EnemySetup> list = instance.enemiesDifficulty1.Concat(instance.enemiesDifficulty2).Concat(instance.enemiesDifficulty3).Where(instance2.IsSupported)
				.ToList();
			foreach (EnemySetup item in list)
			{
				MaliciousHeads.Logger.LogDebug((object)("Removing setup: " + ((Object)item).name));
				instance2.RememberEnemy(item);
				RemoveFromDirector(item);
			}
		}

		private static void RemoveFromDirector(EnemySetup enemy)
		{
			EnemyDirector.instance.enemiesDifficulty1.Remove(enemy);
			EnemyDirector.instance.enemiesDifficulty2.Remove(enemy);
			EnemyDirector.instance.enemiesDifficulty3.Remove(enemy);
		}
	}
	[HarmonyPatch(typeof(PlayerHealth))]
	internal class PlayerHealthPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch("Death")]
		private static void PlayerHealthDeathPostfix()
		{
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			MaliciousHeads.Logger.LogDebug((object)"Player died");
			if (!SemiFunc.IsMultiplayer() || !SemiFunc.IsMasterClient() || !SemiFunc.RunIsLevel())
			{
				return;
			}
			EnemyManager instance = EnemyManager.Instance;
			if (instance.HasEnemiesToRelease())
			{
				foreach (EnemySetup item in instance.ReleaseRememberedEnemies())
				{
					Difficulty? difficulty = GetDifficulty(GetEnemyParent(item));
					if (difficulty.HasValue)
					{
						MaliciousHeads.Logger.LogDebug((object)$"Added {((Object)item).name} to {difficulty}");
						AssignEnemyToDifficulty(item, difficulty.Value);
					}
				}
			}
			EnemySetup enemySetup = default(EnemySetup);
			if (instance.SpawnedHeads < Settings.MaxHeadSpawnsPerLevel.Value && Random.Range(0, 100) < Settings.SpawnChanceOnPlayeDeath.Value && Enemies.TryGetEnemyByName("Malicious Head", ref enemySetup))
			{
				REPOLibUtils.SpawnEnemyNowInVanillaManner(enemySetup);
				instance.SpawnedHeads++;
			}
		}

		private static EnemyParent? GetEnemyParent(EnemySetup enemySetup)
		{
			EnemyParent result = default(EnemyParent);
			foreach (GameObject spawnObject in enemySetup.spawnObjects)
			{
				if (spawnObject.TryGetComponent<EnemyParent>(ref result))
				{
					return result;
				}
			}
			return null;
		}

		private static Difficulty? GetDifficulty(EnemyParent? enemyParent)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)enemyParent == (Object)null)
			{
				return null;
			}
			return enemyParent.difficulty;
		}

		private static void AssignEnemyToDifficulty(EnemySetup enemySetup, Difficulty difficulty)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected I4, but got Unknown
			switch ((int)difficulty)
			{
			case 0:
				EnemyDirector.instance.enemiesDifficulty1.Add(enemySetup);
				break;
			case 1:
				EnemyDirector.instance.enemiesDifficulty2.Add(enemySetup);
				break;
			case 2:
				EnemyDirector.instance.enemiesDifficulty3.Add(enemySetup);
				break;
			}
		}
	}
}
namespace MaliciousHeads.Manager
{
	internal class EnemyManager
	{
		private static readonly ISet<string> _supportedEnemyNames = new HashSet<string> { "Enemy - Malicious Head" };

		private static ISet<EnemySetup> _enemySetups = new HashSet<EnemySetup>();

		internal static EnemyManager Instance { get; private set; } = new EnemyManager();


		public byte SpawnedHeads { get; set; }

		public bool IsSupported(EnemySetup enemySetup)
		{
			return _supportedEnemyNames.Contains(((Object)enemySetup).name);
		}

		public void RememberEnemy(EnemySetup enemySetup)
		{
			_enemySetups.Add(enemySetup);
			MaliciousHeads.Logger.LogDebug((object)("Currently remembering: " + string.Join(", ", _enemySetups)));
		}

		public ISet<EnemySetup> ReleaseRememberedEnemies()
		{
			ISet<EnemySetup> enemySetups = _enemySetups;
			_enemySetups = new HashSet<EnemySetup>();
			return enemySetups;
		}

		public bool HasEnemiesToRelease()
		{
			return _enemySetups.Count > 0;
		}
	}
}