Decompiled source of VoodooEnemy v2.1.0

Bepinex/plugins/VoodooEnemy/VoodooEnemy.dll

Decompiled 10 months ago
using System;
using System.Collections;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using GameNetcodeStuff;
using LethalLib.Modules;
using Microsoft.CodeAnalysis;
using Unity.Netcode;
using UnityEngine;
using VoodooEnemy.NetcodePatcher;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("VoodooEnemy")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("There's a fucking ghost on your screen, and you can't get it off!")]
[assembly: AssemblyFileVersion("2.1.0.0")]
[assembly: AssemblyInformationalVersion("2.1.0")]
[assembly: AssemblyProduct("VoodooEnemy")]
[assembly: AssemblyTitle("VoodooEnemy")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2.1.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
[module: NetcodePatchedAssembly]
internal class <Module>
{
	static <Module>()
	{
	}
}
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace VoodooEnemy
{
	[BepInPlugin("VoodooEnemy", "VoodooEnemy", "2.1.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public static EnemyType VoodooEnemy;

		internal static ManualLogSource Logger;

		public static AudioClip[] teleAudio = (AudioClip[])(object)new AudioClip[1];

		public static AudioClip[] chaseAudioMorning = (AudioClip[])(object)new AudioClip[1];

		public static AudioClip[] chaseAudioNoon = (AudioClip[])(object)new AudioClip[1];

		public static AudioClip[] chaseAudioNight = (AudioClip[])(object)new AudioClip[1];

		public static AudioClip voodooFootsteps = new AudioClip();

		private void Awake()
		{
			Logger = ((BaseUnityPlugin)this).Logger;
			Assets.PopulateAssets();
			VoodooEnemy = Assets.MainAssetBundle.LoadAsset<EnemyType>("VoodooEnemy");
			TerminalNode val = Assets.MainAssetBundle.LoadAsset<TerminalNode>("VoodooEnemyTN");
			TerminalKeyword val2 = Assets.MainAssetBundle.LoadAsset<TerminalKeyword>("VoodooEnemyTK");
			teleAudio[0] = Assets.MainAssetBundle.LoadAsset<AudioClip>("sfx_telep");
			chaseAudioMorning[0] = Assets.MainAssetBundle.LoadAsset<AudioClip>("telep_calm");
			chaseAudioNoon[0] = Assets.MainAssetBundle.LoadAsset<AudioClip>("telep_irritated");
			chaseAudioNight[0] = Assets.MainAssetBundle.LoadAsset<AudioClip>("telep_aggro");
			voodooFootsteps = Assets.MainAssetBundle.LoadAsset<AudioClip>("voodoo footsteps");
			NetworkPrefabs.RegisterNetworkPrefab(VoodooEnemy.enemyPrefab);
			Enemies.RegisterEnemy(VoodooEnemy, 35, (LevelTypes)(-1), (SpawnType)0, val, val2);
			Logger.LogInfo((object)"Plugin VoodooEnemy is loaded!");
			Type[] types = Assembly.GetExecutingAssembly().GetTypes();
			Type[] array = types;
			foreach (Type type in array)
			{
				MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic);
				MethodInfo[] array2 = methods;
				foreach (MethodInfo methodInfo in array2)
				{
					object[] customAttributes = methodInfo.GetCustomAttributes(typeof(RuntimeInitializeOnLoadMethodAttribute), inherit: false);
					if (customAttributes.Length != 0)
					{
						methodInfo.Invoke(null, null);
					}
				}
			}
		}
	}
	public static class Assets
	{
		public static AssetBundle MainAssetBundle;

		public static void PopulateAssets()
		{
			string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
			MainAssetBundle = AssetBundle.LoadFromFile(Path.Combine(directoryName, "modassets"));
			if ((Object)(object)MainAssetBundle == (Object)null)
			{
				Plugin.Logger.LogError((object)"Failed to load custom assets.");
			}
		}
	}
	internal class VoodooEnemyAI : EnemyAI
	{
		public enum AudioPlaying
		{
			None,
			Morning,
			Noon,
			Night
		}

		private enum State
		{
			WaitingForPlayer,
			ChasingPlayer,
			LookingForPlayer
		}

		public Transform turnCompass;

		public Transform attackArea;

		public GameObject voodooBody;

		public GameObject booshBody;

		private Vector3 spawnPosition;

		private Vector3 spawnRotation;

		private float secondsSinceLastSawPlayer;

		private bool currentlyTeleporting;

		private Vector3 destinationPos;

		private float audioFade;

		private Random ventRand;

		public AudioPlaying currentAudio = AudioPlaying.None;

		public override void Start()
		{
			//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_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			((EnemyAI)this).Start();
			booshBody.SetActive(false);
			spawnPosition = base.serverPosition;
			spawnRotation = base.serverRotation;
			Plugin.Logger.LogInfo((object)((object)(Vector3)(ref spawnPosition)).ToString());
			((EnemyAI)this).SetClientCalculatingAI(true);
			currentAudio = AudioPlaying.None;
			audioFade = 0f;
			base.currentBehaviourStateIndex = 0;
			base.creatureSFX.clip = Plugin.voodooFootsteps;
			base.agent.speed = 6f;
			base.agent.acceleration = 0f;
			ventRand = new Random(StartOfRound.Instance.randomMapSeed + base.thisEnemyIndex);
			int num = ventRand.Next(1, 101);
			if (num == 69)
			{
				voodooBody.SetActive(false);
				booshBody.SetActive(true);
			}
		}

		public override void Update()
		{
			((EnemyAI)this).Update();
			switch (base.currentBehaviourStateIndex)
			{
			case 0:
				secondsSinceLastSawPlayer += Time.deltaTime;
				break;
			case 2:
				secondsSinceLastSawPlayer += Time.deltaTime;
				break;
			}
			float timeSinceRoundStarted = StartOfRound.Instance.timeSinceRoundStarted;
			float num = timeSinceRoundStarted;
			if (!(num < 200f))
			{
				if (!(num < 380f))
				{
					if (num > 380f && currentAudio != AudioPlaying.Night)
					{
						currentAudio = AudioPlaying.Night;
					}
				}
				else if (currentAudio != AudioPlaying.Noon)
				{
					currentAudio = AudioPlaying.Noon;
				}
			}
			else if (currentAudio != AudioPlaying.Morning)
			{
				currentAudio = AudioPlaying.Morning;
			}
		}

		public override void DoAIInterval()
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0273: Unknown result type (might be due to invalid IL or missing references)
			((EnemyAI)this).DoAIInterval();
			if (((EnemyAI)this).TargetClosestPlayer(0.5f, true, 260f))
			{
				secondsSinceLastSawPlayer = 0f;
				if (base.currentBehaviourStateIndex != 1 && base.targetPlayer.HasLineOfSightToPosition(((Component)this).transform.position, 70f, 25, -1f))
				{
					if (base.currentBehaviourStateIndex == 0)
					{
					}
					GameNetworkManager.Instance.localPlayerController.JumpToFearLevel(0.7f, true);
					((EnemyAI)this).SwitchToBehaviourClientRpc(1);
					base.creatureSFX.Play();
					((MonoBehaviour)this).StartCoroutine(AccelerationDuringChase());
				}
				destinationPos = ((Component)base.targetPlayer).transform.position;
				((EnemyAI)this).SetDestinationToPosition(destinationPos, false);
				((EnemyAI)this).SetMovingTowardsTargetPlayer(base.targetPlayer);
			}
			else
			{
				PlayerControllerB targetPlayer = base.targetPlayer;
				base.targetPlayer = ((EnemyAI)this).GetClosestPlayer(false, false, false);
				if ((Object)(object)base.targetPlayer == (Object)null)
				{
					secondsSinceLastSawPlayer = 0f;
					if (base.currentBehaviourStateIndex != 0)
					{
						((EnemyAI)this).SwitchToBehaviourClientRpc(0);
					}
					((EnemyAI)this).SetMovingTowardsTargetPlayer((PlayerControllerB)null);
					((EnemyAI)this).SetDestinationToPosition(spawnPosition, false);
					return;
				}
				if (((NetworkBehaviour)this).OwnerClientId != base.targetPlayer.actualClientId)
				{
					((EnemyAI)this).ChangeOwnershipOfEnemy(base.targetPlayer.actualClientId);
				}
				if (base.currentBehaviourStateIndex == 1)
				{
					((EnemyAI)this).SwitchToBehaviourClientRpc(2);
				}
				if (secondsSinceLastSawPlayer > 3f)
				{
					if (base.currentBehaviourStateIndex != 0)
					{
						((EnemyAI)this).SwitchToBehaviourClientRpc(0);
					}
					((EnemyAI)this).SetDestinationToPosition(spawnPosition, false);
					if (Mathf.Abs(Vector3.Distance(((Component)this).transform.position, spawnPosition)) < 3f)
					{
						base.agent.acceleration = 0f;
						base.creatureSFX.Stop();
					}
					if (secondsSinceLastSawPlayer > (float)ventRand.Next(30, 60))
					{
						TeleportVoodooToCloseVent();
					}
				}
				if (((EnemyAI)this).TargetClosestPlayer(0.5f, false, 360f) && base.currentBehaviourStateIndex == 0)
				{
					((Component)this).transform.LookAt(((Component)base.targetPlayer).transform.position);
				}
			}
			((EnemyAI)this).SyncPositionToClients();
		}

		public override void OnCollideWithPlayer(Collider other)
		{
			PlayerControllerB val = ((EnemyAI)this).MeetsStandardPlayerCollisionConditions(other, false, false);
			if ((Object)(object)val != (Object)null && !currentlyTeleporting)
			{
				TeleportPlayerToRandomPos(val);
			}
		}

		public void TeleportPlayerToRandomPos(PlayerControllerB player)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			currentlyTeleporting = true;
			Random random = new Random();
			Vector3 position = RoundManager.Instance.insideAINodes[random.Next(0, RoundManager.Instance.insideAINodes.Length)].transform.position;
			while (Vector3.Distance(position, ((Component)this).transform.position) < 30f)
			{
				position = RoundManager.Instance.insideAINodes[random.Next(0, RoundManager.Instance.insideAINodes.Length)].transform.position;
			}
			player.DropAllHeldItemsAndSync();
			player.TeleportPlayer(position, false, 0f, false, true);
			Plugin.Logger.LogInfo((object)"voodoo attempted to teleport player");
			player.DamagePlayer(20, true, true, (CauseOfDeath)0, 0, false, default(Vector3));
			player.SpawnPlayerAnimation();
			if (player.statusEffectAudio.isPlaying)
			{
				player.statusEffectAudio.Stop();
				player.statusEffectAudio.clip = null;
			}
			RoundManager.PlayRandomClip(player.statusEffectAudio, Plugin.teleAudio, false, 1f, 0);
			currentlyTeleporting = false;
		}

		public void TeleportVoodooToCloseVent()
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			float[] array = new float[RoundManager.Instance.allEnemyVents.Length];
			EnemyVent[] array2 = (EnemyVent[])(object)new EnemyVent[RoundManager.Instance.allEnemyVents.Length];
			for (int i = 0; i < RoundManager.Instance.allEnemyVents.Length; i++)
			{
				float num = Vector3.Distance(((Component)RoundManager.Instance.allEnemyVents[i]).transform.position, ((Component)base.targetPlayer).transform.position);
				array[i] = num;
				array2[i] = RoundManager.Instance.allEnemyVents[i];
			}
			Array.Sort(array, array2);
			for (int j = 0; j < array.Length; j++)
			{
				if (array[j] > 20f)
				{
					((Component)this).transform.position = ((Component)array2[j]).transform.position;
					((EnemyAI)this).SyncPositionToClients();
					secondsSinceLastSawPlayer = 0f;
					spawnPosition = ((Component)array2[j]).transform.position;
					break;
				}
			}
			Plugin.Logger.LogInfo((object)("Teleported Voodoo closer to player " + ((object)base.targetPlayer).ToString()));
		}

		public IEnumerator AccelerationDuringChase()
		{
			yield return (object)new WaitForSeconds(0.5f);
			base.agent.acceleration = 2.5f;
			yield return (object)new WaitForSeconds(3f);
			base.agent.acceleration = 9999f;
		}

		public void VoodooSoundHandler(AudioPlaying currentAudio)
		{
			switch (currentAudio)
			{
			case AudioPlaying.Morning:
				base.targetPlayer.statusEffectAudio.clip = Plugin.chaseAudioMorning[0];
				((MonoBehaviour)this).StartCoroutine(FadeAudio(base.targetPlayer.statusEffectAudio));
				break;
			case AudioPlaying.Noon:
				base.targetPlayer.statusEffectAudio.clip = Plugin.chaseAudioNoon[0];
				((MonoBehaviour)this).StartCoroutine(FadeAudio(base.targetPlayer.statusEffectAudio));
				break;
			case AudioPlaying.Night:
				base.targetPlayer.statusEffectAudio.clip = Plugin.chaseAudioNight[0];
				((MonoBehaviour)this).StartCoroutine(FadeAudio(base.targetPlayer.statusEffectAudio));
				break;
			}
		}

		private IEnumerator FadeAudio(AudioSource audioSource)
		{
			if (audioSource.isPlaying)
			{
				while (audioSource.volume > 0f)
				{
					yield return (object)new WaitForSeconds(0.025f);
					audioSource.volume -= 0.025f;
				}
				audioSource.Stop();
				audioSource.clip = null;
			}
			else
			{
				audioSource.Play();
				while (audioSource.volume < 1f)
				{
					yield return (object)new WaitForSeconds(0.025f);
					audioSource.volume += 0.025f;
				}
			}
		}

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

		protected internal override string __getTypeName()
		{
			return "VoodooEnemyAI";
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "VoodooEnemy";

		public const string PLUGIN_NAME = "VoodooEnemy";

		public const string PLUGIN_VERSION = "2.1.0";
	}
}
namespace VoodooEnemy.NetcodePatcher
{
	[AttributeUsage(AttributeTargets.Module)]
	internal class NetcodePatchedAssemblyAttribute : Attribute
	{
	}
}