Decompiled source of MaskedEnemyOverhaulFork v3.3.0

MaskedEnemyRework.dll

Decompiled 5 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using MaskedEnemyRework.Patches;
using Microsoft.CodeAnalysis;
using MoreCompany;
using MoreCompany.Cosmetics;
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: AssemblyCompany("MaskedEnemyRework")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Lethal Company Mod")]
[assembly: AssemblyFileVersion("3.3.0.0")]
[assembly: AssemblyInformationalVersion("3.3.0")]
[assembly: AssemblyProduct("MaskedEnemyRework")]
[assembly: AssemblyTitle("MaskedEnemyRework")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("3.3.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace MaskedEnemyRework
{
	public class PluginConfig
	{
		public bool RemoveMasks = Cfg("General", "Remove Mask From Masked Enemy", defaultVal: true, "Whether or not the Masked Enemy has a mask on.");

		public bool RevealMasks = Cfg("General", "Reveal Mask When Attacking", defaultVal: false, "The enemy would reveal their mask permanently after trying to attack someone. Mask would be off until the attempt to attack is made");

		public bool RemoveZombieArms = Cfg("General", "Remove Zombie Arms", defaultVal: true, "Remove the animation where the Masked raise arms like a zombie.");

		public bool TriggerMines = Cfg("General", "Masked Trigger Mines", defaultVal: true, "Masked go KABOOM when walking over a mine.");

		public int Health = Cfg("General", "Masked Health", 4, "Number of shovel hits required to kill a Masked.");

		public bool UseVanillaSpawns = Cfg("General", "Use Vanilla Spawns", defaultVal: false, "Disables all spawning rules from this mod. Only uses the above settings from this config. Will not spawn on all moons. will ignore EVERYTHING in the config below this point.");

		public bool DontTouchMimickingPlayer = Cfg("General", "Dont Touch MaskedPlayerEnemy.mimickingPlayer", defaultVal: false, "Experimental. Give control to other mods (like qwbarch-Mirage) to set which players are impersonated.");

		public bool ShowMaskedNames = Cfg("General", "Show Masked Usernames", defaultVal: false, "[UNUSED FOR NOW] Will show username of player being mimicked.");

		public bool UseSpawnRarity = Cfg("Spawns", "Use Spawn Rarity", defaultVal: false, "Use custom spawn rate from config. If this is false, the masked spawns at the same rate as the Bracken. If true, will spawn at whatever rarity is given in Spawn Rarity config option");

		public int SpawnRarity = Cfg("Spawns", "Spawn Rarity", 15, "The rarity for the Masked Enemy to spawn. The higher the number, the more likely to spawn. Can go to 1000000000, any higher will break. Use Spawn Rarity must be set to True");

		public bool CanSpawnOutside = Cfg("Spawns", "Allow Masked To Spawn Outside", defaultVal: false, "Whether the Masked Enemy can spawn outside the building");

		public int MaxSpawnCount = Cfg("Spawns", "Max Number of Masked", 3, "Vents will stop spawning Masked when this limit is hit. Masked can still spawn through other means, like players getting possessed.");

		public float PowerLevel = Cfg("Spawns", "Masked Power Level", 1f, "How much of the moon's Power Level each Masked consumes. Higher = Less entities");

		public bool BoostMoonPowerLevel = Cfg("Spawns", "Boost Moon Power Level", defaultVal: false, "Increase moon indoor max power level by (Max Masked * Masked Power Level). Allows more Masked and other monsters to spawn. Original MEO behavior.");

		public bool ZombieApocalypseMode = Cfg("Zombie Apocalypse Mode", "Always Zombie Apocalypse", defaultVal: false, "Only spawns Masked! Make sure to crank up the Max Spawn Count in this config! Would also recommend bringing a gun (mod), a shovel works fine too though.... This mode does not play nice with other mods that affect spawn rates. Disable those before playing for best results");

		public int ZombieApocalypeRandomChance = Cfg("Zombie Apocalypse Mode", "Random Zombie Apocalypse", -1, "[Must Be Whole Number] The percent chance from 1 to 100 that a day could contain a zombie apocalypse. Put at -1 to never have the chance arise and don't have Only Spawn Masked turned on");

		public int MaxZombies = Cfg("Zombie Apocalypse Mode", "Max Zombies", 6, "Max Masked for Zombie Apocalypse. Vents will stop spawning Masked when this limit is hit.");

		public float ZombiePowerLevel = Cfg("Zombie Apocalypse Mode", "Zombie Power Level", 2f, "Masked power level during Zombie Apocalypse. Higher = Less Zombies. This can limit max zombies by moon difficulty, even if it's lower than what the 'Max Zombies' option allows. Set to 0 to use Max Zombies for all moons. Moon Indoor Power Levels for reference: [Experimentation: 4, Offense: 12, Titan: 18]");

		public bool UseZombieSpawnCurve = Cfg("Zombie Apocalypse Mode", "Use Spawn Curves", defaultVal: false, "[BUGGED: This likely permanently modifies the level spawning options until the game is restarted] Edit level spawn curves during a Zombie Apocalypse; options below. Original MEO behavior.");

		public float InsideEnemySpawnCurve = Cfg("Zombie Apocalypse Mode", "StartOfDay Inside Masked Spawn Curve", 0.1f, "Spawn curve for masked inside, start of the day. Crank this way up for immediate action. More info in the readme");

		public float MiddayInsideEnemySpawnCurve = Cfg("Zombie Apocalypse Mode", "Midday Inside Masked Spawn Curve", 500f, "Spawn curve for masked inside, midday.");

		public float StartOutsideEnemySpawnCurve = Cfg("Zombie Apocalypse Mode", "StartOfDay Masked Outside Spawn Curve", -30f, "Spawn curve for outside masked, start of the day.");

		public float MidOutsideEnemySpawnCurve = Cfg("Zombie Apocalypse Mode", "Midday Outside Masked Spawn Curve", -30f, "Spawn curve for outside masked, midday.");

		public float EndOutsideEnemySpawnCurve = Cfg("Zombie Apocalypse Mode", "EOD Outside Masked Spawn Curve", 10f, "Spawn curve for outside masked, end of day");

		public static List<ConfigEntryBase> entries = new List<ConfigEntryBase>();

		public static T Cfg<T>(string category, string name, T defaultVal, string description)
		{
			ConfigEntry<T> val = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<T>(category, name, defaultVal, description);
			entries.Add((ConfigEntryBase)(object)val);
			return val.Value;
		}
	}
	[BepInPlugin("MaskedEnemyRework", "MaskedEnemyRework", "3.3.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		private readonly Harmony harmony = new Harmony("MaskedEnemyRework");

		public static Plugin Instance;

		public static ManualLogSource logger;

		public static PluginConfig cfg;

		public static List<int> PlayerMimicList;

		public static int PlayerMimicIndex;

		public static int InitialPlayerCount;

		public static SpawnableEnemyWithRarity maskedPrefab;

		public static SpawnableEnemyWithRarity flowerPrefab;

		private void Awake()
		{
			if ((Object)(object)Instance == (Object)null)
			{
				Instance = this;
			}
			PlayerMimicList = new List<int>();
			PlayerMimicIndex = 0;
			InitialPlayerCount = 0;
			cfg = new PluginConfig();
			logger = Logger.CreateLogSource("MaskedEnemyRework");
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin MaskedEnemyRework is loaded! Woohoo!");
			harmony.PatchAll(typeof(Plugin));
			harmony.PatchAll(typeof(GetMaskedPrefabForLaterUse));
			harmony.PatchAll(typeof(MaskedVisualRework));
			harmony.PatchAll(typeof(MaskedSpawnSettings));
			if (cfg.TriggerMines)
			{
				harmony.PatchAll(typeof(LandmineVsMasked));
			}
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "MaskedEnemyRework";

		public const string PLUGIN_NAME = "MaskedEnemyRework";

		public const string PLUGIN_VERSION = "3.3.0";
	}
}
namespace MaskedEnemyRework.Patches
{
	[HarmonyPatch]
	internal class GetMaskedPrefabForLaterUse
	{
		[HarmonyPatch(typeof(Terminal), "Start")]
		[HarmonyPostfix]
		private static void SavesPrefabForLaterUse(ref SelectableLevel[] ___moonsCatalogueList)
		{
			ManualLogSource val = Logger.CreateLogSource("MaskedEnemyRework");
			SelectableLevel[] array = ___moonsCatalogueList;
			for (int i = 0; i < array.Length; i++)
			{
				foreach (SpawnableEnemyWithRarity enemy in array[i].Enemies)
				{
					if (enemy.enemyType.enemyName == "Masked")
					{
						val.LogInfo((object)"Found Masked!");
						Plugin.maskedPrefab = enemy;
					}
					else if (enemy.enemyType.enemyName == "Flowerman")
					{
						Plugin.flowerPrefab = enemy;
						val.LogInfo((object)"Found Flowerman!");
					}
				}
			}
		}

		[HarmonyPatch(typeof(PlayerControllerB), "SetHoverTipAndCurrentInteractTrigger")]
		[HarmonyPrefix]
		private static void LookingAtMasked(ref PlayerControllerB __instance)
		{
			//IL_001b: 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_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_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.cfg.ShowMaskedNames)
			{
				return;
			}
			Ray val = default(Ray);
			((Ray)(ref val))..ctor(((Component)__instance.gameplayCamera).transform.position, ((Component)__instance.gameplayCamera).transform.forward);
			LayerMask val2 = LayerMask.op_Implicit(524288);
			RaycastHit val3 = default(RaycastHit);
			if (!__instance.isFreeCamera && Physics.Raycast(val, ref val3, 5f, LayerMask.op_Implicit(val2)))
			{
				EnemyAICollisionDetect component = ((Component)((RaycastHit)(ref val3)).collider).gameObject.GetComponent<EnemyAICollisionDetect>();
				if (Object.op_Implicit((Object)(object)component))
				{
					((Component)component.mainScript).gameObject.GetComponent<MaskedPlayerEnemy>();
				}
			}
		}
	}
	[HarmonyPatch(typeof(Landmine))]
	internal class LandmineVsMasked
	{
		[HarmonyPatch("OnTriggerEnter")]
		[HarmonyPostfix]
		private static void OnTriggerEnter(Collider other, Landmine __instance, ref bool ___hasExploded, ref float ___pressMineDebounceTimer)
		{
			if (!___hasExploded && !(___pressMineDebounceTimer > 0f) && ((Component)other).CompareTag("Player") && ((Object)other).name.StartsWith("Masked"))
			{
				___pressMineDebounceTimer = 0.5f;
				__instance.PressMineServerRpc();
			}
		}

		[HarmonyPatch("OnTriggerExit")]
		[HarmonyPostfix]
		private static void OnTriggerExit(Collider other, Landmine __instance, ref bool ___hasExploded, ref bool ___mineActivated)
		{
			if (!___hasExploded && ___mineActivated && ((Component)other).CompareTag("Player") && ((Object)other).name.StartsWith("Masked"))
			{
				typeof(Landmine).GetMethod("TriggerMineOnLocalClientByExiting", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(__instance, null);
			}
		}
	}
	[HarmonyPatch(typeof(RoundManager))]
	internal class MaskedSpawnSettings
	{
		private static Predicate<SpawnableEnemyWithRarity> isMasked = (SpawnableEnemyWithRarity enemy) => enemy.enemyType.enemyName == "Masked";

		private static Predicate<SpawnableEnemyWithRarity> isFlowerman = (SpawnableEnemyWithRarity enemy) => enemy.enemyType.enemyName == "Flowerman";

		private static FieldInfo powerLevelField = typeof(EnemyType).GetField("PowerLevel");

		private static FieldInfo currentMaxInsidePowerField = typeof(RoundManager).GetField("currentMaxInsidePower");

		public static bool isZombieApocalypse = false;

		public static T StupidGet<T>(object obj, FieldInfo field)
		{
			return (T)Convert.ChangeType(field.GetValue(obj), typeof(T));
		}

		[HarmonyPatch("BeginEnemySpawning")]
		[HarmonyPrefix]
		private static void UpdateSpawnRates(ref SelectableLevel ___currentLevel)
		{
			//IL_0202: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: Unknown result type (might be due to invalid IL or missing references)
			//IL_021e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			//IL_0232: Expected O, but got Unknown
			//IL_0246: Unknown result type (might be due to invalid IL or missing references)
			//IL_024b: Unknown result type (might be due to invalid IL or missing references)
			//IL_025c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0261: Unknown result type (might be due to invalid IL or missing references)
			//IL_026b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0275: Expected O, but got Unknown
			//IL_028a: Unknown result type (might be due to invalid IL or missing references)
			//IL_028f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d1: Expected O, but got Unknown
			PluginConfig cfg = Plugin.cfg;
			if (cfg.UseVanillaSpawns)
			{
				return;
			}
			ManualLogSource logger = Plugin.logger;
			logger.LogInfo((object)"Starting Round Manager");
			SpawnableEnemyWithRarity maskedPrefab = Plugin.maskedPrefab;
			SpawnableEnemyWithRarity val = ___currentLevel.Enemies.Find(isFlowerman) ?? Plugin.flowerPrefab;
			isZombieApocalypse = cfg.ZombieApocalypseMode || StartOfRound.Instance.randomMapSeed % 100 < cfg.ZombieApocalypeRandomChance;
			try
			{
				maskedPrefab.enemyType.enemyPrefab.GetComponent<EnemyAI>().enemyHP = cfg.Health;
				float num = 0f;
				foreach (SpawnableEnemyWithRarity item in ___currentLevel.Enemies.FindAll(isMasked))
				{
					num -= (float)item.enemyType.MaxCount * StupidGet<float>(item.enemyType, powerLevelField);
				}
				___currentLevel.Enemies.RemoveAll(isMasked);
				___currentLevel.Enemies.Add(maskedPrefab);
				if (cfg.CanSpawnOutside)
				{
					___currentLevel.OutsideEnemies.RemoveAll(isMasked);
					___currentLevel.OutsideEnemies.Add(maskedPrefab);
					___currentLevel.DaytimeEnemies.RemoveAll(isMasked);
					___currentLevel.DaytimeEnemies.Add(maskedPrefab);
				}
				float num2 = (isZombieApocalypse ? cfg.ZombiePowerLevel : cfg.PowerLevel);
				powerLevelField.SetValue(maskedPrefab.enemyType, Convert.ChangeType(num2, powerLevelField.FieldType));
				maskedPrefab.enemyType.probabilityCurve = val.enemyType.probabilityCurve;
				maskedPrefab.enemyType.isOutsideEnemy = cfg.CanSpawnOutside;
				if (isZombieApocalypse)
				{
					logger.LogInfo((object)"ZOMBIE APOCALYPSE");
					maskedPrefab.enemyType.MaxCount = cfg.MaxZombies;
					maskedPrefab.rarity = 1000000;
					if (cfg.UseZombieSpawnCurve)
					{
						___currentLevel.enemySpawnChanceThroughoutDay = new AnimationCurve((Keyframe[])(object)new Keyframe[2]
						{
							new Keyframe(0f, cfg.InsideEnemySpawnCurve),
							new Keyframe(0.5f, cfg.MiddayInsideEnemySpawnCurve)
						});
						___currentLevel.daytimeEnemySpawnChanceThroughDay = new AnimationCurve((Keyframe[])(object)new Keyframe[2]
						{
							new Keyframe(0f, 7f),
							new Keyframe(0.5f, 7f)
						});
						___currentLevel.outsideEnemySpawnChanceThroughDay = new AnimationCurve((Keyframe[])(object)new Keyframe[3]
						{
							new Keyframe(0f, cfg.StartOutsideEnemySpawnCurve),
							new Keyframe(20f, cfg.MidOutsideEnemySpawnCurve),
							new Keyframe(21f, cfg.EndOutsideEnemySpawnCurve)
						});
					}
				}
				else
				{
					logger.LogInfo((object)"no zombies :(");
					maskedPrefab.enemyType.MaxCount = cfg.MaxSpawnCount;
					maskedPrefab.rarity = (cfg.UseSpawnRarity ? cfg.SpawnRarity : val.rarity);
				}
				num += (float)maskedPrefab.enemyType.MaxCount * num2;
				if (cfg.BoostMoonPowerLevel)
				{
					logger.LogInfo((object)$"Adjusting power levels: [maxEnemyPowerCount: {___currentLevel.maxEnemyPowerCount}+{num}, maxDaytimeEnemyPowerCount: {___currentLevel.maxDaytimeEnemyPowerCount}+{num}, maxOutsideEnemyPowerCount: {___currentLevel.maxOutsideEnemyPowerCount}+{num}]");
					SelectableLevel obj = ___currentLevel;
					obj.maxEnemyPowerCount += (int)num;
					SelectableLevel obj2 = ___currentLevel;
					obj2.maxDaytimeEnemyPowerCount += (int)num;
					SelectableLevel obj3 = ___currentLevel;
					obj3.maxOutsideEnemyPowerCount += (int)num;
				}
			}
			catch (Exception ex)
			{
				logger.LogInfo((object)ex);
			}
		}

		[HarmonyPatch("AssignRandomEnemyToVent")]
		[HarmonyPrefix]
		private static bool ZombieVent(EnemyVent vent, float spawnTime, ref RoundManager __instance, ref bool __result, ref SelectableLevel ___currentLevel, ref TimeOfDay ___timeScript, ref bool ___cannotSpawnMoreInsideEnemies, ref bool ___firstTimeSpawningEnemies, ref int ___currentEnemyPower, ref int ___currentHour)
		{
			if (Plugin.cfg.UseVanillaSpawns || !isZombieApocalypse)
			{
				return true;
			}
			if (___firstTimeSpawningEnemies)
			{
				foreach (SpawnableEnemyWithRarity enemy in ___currentLevel.Enemies)
				{
					enemy.enemyType.numberSpawned = 0;
				}
			}
			___firstTimeSpawningEnemies = false;
			ManualLogSource logger = Plugin.logger;
			int num = ___currentLevel.Enemies.FindIndex(isMasked);
			SpawnableEnemyWithRarity val = ___currentLevel.Enemies[num];
			if (num == -1)
			{
				logger.LogInfo((object)"No masked found in enemy list?");
				return true;
			}
			if (val.enemyType.numberSpawned >= val.enemyType.MaxCount)
			{
				__result = false;
				___cannotSpawnMoreInsideEnemies = true;
				logger.LogInfo((object)"Max masked spawned");
				return false;
			}
			float num2 = StupidGet<float>(val.enemyType, powerLevelField);
			float num3 = StupidGet<float>(__instance, currentMaxInsidePowerField) - (float)___currentEnemyPower;
			logger.LogInfo((object)("available inside power: " + num3));
			if (num2 > num3)
			{
				__result = false;
				___cannotSpawnMoreInsideEnemies = true;
				logger.LogInfo((object)"Max power");
				return false;
			}
			___currentEnemyPower += (int)num2;
			vent.enemyType = val.enemyType;
			vent.enemyTypeIndex = num;
			vent.occupied = true;
			vent.spawnTime = spawnTime;
			if (___timeScript.hour - ___currentHour > 0)
			{
				logger.LogInfo((object)"Round manager catching up to time yada yada UvU.");
			}
			else
			{
				vent.SyncVentSpawnTimeClientRpc((int)spawnTime, num);
			}
			EnemyType enemyType = val.enemyType;
			enemyType.numberSpawned++;
			logger.LogInfo((object)"Spawned a masked");
			__result = true;
			return false;
		}
	}
	[HarmonyPatch(typeof(MaskedPlayerEnemy))]
	internal class MaskedVisualRework
	{
		private static IEnumerator coroutine;

		[HarmonyPatch("Start")]
		[HarmonyBefore(new string[] { "AdvancedCompany" })]
		[HarmonyPostfix]
		private static void ReformVisuals(ref MaskedPlayerEnemy __instance)
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			ManualLogSource val = Logger.CreateLogSource("MaskedEnemyRework");
			if (!Plugin.cfg.DontTouchMimickingPlayer)
			{
				PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
				int num = StartOfRound.Instance.ClientPlayerList.Count;
				if (num == 0)
				{
					num = 1;
					val.LogError((object)"Player count was zero");
				}
				if (Plugin.PlayerMimicList.Count <= 1 || Plugin.InitialPlayerCount != num)
				{
					Plugin.InitialPlayerCount = num;
					State state = Random.state;
					Random.InitState(1234);
					for (int i = 0; i < 50; i++)
					{
						Plugin.PlayerMimicList.Add(Random.Range(0, num));
					}
					Random.state = state;
				}
				int num2 = Plugin.PlayerMimicList[Plugin.PlayerMimicIndex % 50] % num;
				Plugin.PlayerMimicIndex++;
				if ((Object)(object)__instance.mimickingPlayer == (Object)null)
				{
					__instance.mimickingPlayer = allPlayerScripts[num2];
				}
				__instance.SetSuit(__instance.mimickingPlayer.currentSuitID);
			}
			if (Plugin.cfg.RemoveMasks || Plugin.cfg.RevealMasks)
			{
				((Component)((Component)__instance).gameObject.transform.Find("ScavengerModel/metarig/spine/spine.001/spine.002/spine.003/spine.004/HeadMaskComedy")).gameObject.SetActive(false);
				((Component)((Component)__instance).gameObject.transform.Find("ScavengerModel/metarig/spine/spine.001/spine.002/spine.003/spine.004/HeadMaskTragedy")).gameObject.SetActive(false);
			}
			if (Chainloader.PluginInfos.ContainsKey("me.swipez.melonloader.morecompany") && !Chainloader.PluginInfos.ContainsKey("com.potatoepet.AdvancedCompany"))
			{
				MoreCompanyPatch.ApplyCosmetics(__instance);
			}
		}

		[HarmonyPatch("SetHandsOutClientRpc")]
		[HarmonyPrefix]
		private static void MaskAndArmsReveal(ref bool setOut, ref MaskedPlayerEnemy __instance)
		{
			GameObject gameObject = ((Component)((Component)__instance).gameObject.transform.Find("ScavengerModel/metarig/spine/spine.001/spine.002/spine.003/spine.004/HeadMaskComedy")).gameObject;
			if (Plugin.cfg.RevealMasks && !gameObject.activeSelf && ((EnemyAI)__instance).currentBehaviourStateIndex == 1)
			{
				Logger.CreateLogSource("MaskedEnemyRework");
				IEnumerator enumerator = FadeInAndOut(gameObject, fadeIn: true, 1f);
				((MonoBehaviour)__instance).StartCoroutine(enumerator);
			}
			if (Plugin.cfg.RemoveZombieArms)
			{
				setOut = false;
			}
		}

		[HarmonyPatch("SetEnemyOutside")]
		[HarmonyPostfix]
		[HarmonyPriority(300)]
		private static void HideCosmeticsIfMarked(ref MaskedPlayerEnemy __instance)
		{
			if (Chainloader.PluginInfos.ContainsKey("me.swipez.melonloader.morecompany") && !Chainloader.PluginInfos.ContainsKey("com.potatoepet.AdvancedCompany"))
			{
				MoreCompanyPatch.ApplyCosmetics(__instance);
			}
		}

		[HarmonyPatch("DoAIInterval")]
		[HarmonyPostfix]
		private static void HideRevealedMask(ref MaskedPlayerEnemy __instance)
		{
			if (Plugin.cfg.RevealMasks && (Object)(object)((EnemyAI)__instance).targetPlayer == (Object)null)
			{
				GameObject gameObject = ((Component)((Component)__instance).gameObject.transform.Find("ScavengerModel/metarig/spine/spine.001/spine.002/spine.003/spine.004/HeadMaskComedy")).gameObject;
				if (gameObject.activeSelf)
				{
					IEnumerator enumerator = FadeInAndOut(gameObject, fadeIn: false, 1f);
					((MonoBehaviour)__instance).StartCoroutine(enumerator);
				}
			}
		}

		[HarmonyPatch("Update")]
		[HarmonyPostfix]
		private static void UpdateMaskName(ref MaskedPlayerEnemy __instance)
		{
		}

		private static IEnumerator FadeInAndOut(GameObject mask, bool fadeIn, float duration)
		{
			float counter = 0f;
			mask.SetActive(true);
			float startLoc;
			float endLoc;
			if (fadeIn)
			{
				startLoc = 0.095f;
				endLoc = 0.215f;
			}
			else
			{
				startLoc = 0.215f;
				endLoc = 0.095f;
			}
			while (counter < duration)
			{
				counter += Time.deltaTime;
				float num = Mathf.Lerp(startLoc, endLoc, counter / duration);
				mask.transform.localPosition = new Vector3(-0.009f, 0.143f, num);
				yield return null;
			}
			if (!fadeIn)
			{
				mask.SetActive(false);
			}
		}
	}
	internal class MoreCompanyPatch
	{
		public static void ApplyCosmetics(MaskedPlayerEnemy masked)
		{
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			if (MainClass.playerIdsAndCosmetics.Count == 0)
			{
				return;
			}
			FieldInfo field = typeof(MainClass).GetField("showCosmetics");
			FieldInfo field2 = typeof(MainClass).GetField("cosmeticsSyncOther");
			if (field != null)
			{
				if (!(bool)field.GetValue(null))
				{
					return;
				}
			}
			else if (!(field2 != null) || !((ConfigEntry<bool>)field2.GetValue(null)).Value)
			{
				return;
			}
			Transform val = ((Component)masked).transform.Find("ScavengerModel").Find("metarig");
			CosmeticApplication component = ((Component)val).GetComponent<CosmeticApplication>();
			if (Object.op_Implicit((Object)(object)component))
			{
				component.ClearCosmetics();
				Object.Destroy((Object)(object)component);
				((EnemyAI)masked).skinnedMeshRenderers = ((Component)masked).gameObject.GetComponentsInChildren<SkinnedMeshRenderer>();
				((EnemyAI)masked).meshRenderers = ((Component)masked).gameObject.GetComponentsInChildren<MeshRenderer>();
			}
			List<string> list = MainClass.playerIdsAndCosmetics[(int)masked.mimickingPlayer.playerClientId];
			component = ((Component)val).gameObject.AddComponent<CosmeticApplication>();
			foreach (string item in list)
			{
				component.ApplyCosmetic(item, true);
			}
			foreach (CosmeticInstance spawnedCosmetic in component.spawnedCosmetics)
			{
				Transform transform = ((Component)spawnedCosmetic).transform;
				transform.localScale *= 0.38f;
			}
		}
	}
	internal class RemoveZombieArms
	{
		[HarmonyPatch(typeof(MaskedPlayerEnemy), "SetHandsOutClientRpc")]
		[HarmonyPrefix]
		private static void RemoveArms(ref bool setOut)
		{
			if (Plugin.cfg.RemoveZombieArms)
			{
				setOut = false;
			}
		}
	}
}