Decompiled source of Mantle v1.0.2

plugins/Mantle-Lembont/Lembont.MantleEnemy.dll

Decompiled 3 months ago
using System;
using System.Collections;
using System.Collections.Generic;
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.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using Lembont.MantleEnemy.NetcodePatcher;
using LethalLib.Modules;
using MantleEnemy.Configuration;
using Microsoft.CodeAnalysis;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.AI;

[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("Lembont.MantleEnemy")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("MantleEnemy")]
[assembly: AssemblyTitle("Lembont.MantleEnemy")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
[module: NetcodePatchedAssembly]
internal class <Module>
{
	static <Module>()
	{
	}
}
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.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 MantleEnemy
{
	internal class MantleEnemyAI : EnemyAI
	{
		private enum State
		{
			SearchingForPlayer,
			MovingTowardsPlayer,
			Patrolling,
			Fleeing
		}

		public AudioSource audioSource;

		public AudioClip mantle_footstep;

		public AudioClip mantle_roar;

		public AudioClip roam_sound;

		public Transform turnCompass = null;

		public float normalSpeed = 3f;

		public float chaseSpeed = 5f;

		public float chargeSpeed = 15f;

		public float fleeSpeed = 7f;

		public float stunDuration = 3f;

		public float damageAmount = 10f;

		public float maxHealth = 100f;

		public float wanderRadius = 20f;

		public float wanderTimer = 5f;

		private Animator animator;

		private bool isCharging = false;

		private bool isStunned = false;

		private bool isFleeing = false;

		private float currentHealth;

		private float stunEndTime;

		private bool knockbackApplied = false;

		private float knockbackCooldownTime = 1f;

		private float lastKnockbackTime = float.NegativeInfinity;

		private NavMeshAgent navMeshAgent;

		private float timer;

		private float footstepTimer = 0f;

		private float footstepInterval = 0.5f;

		private float healthThreshold = 20f;

		private float lastStateChangeTime = 0f;

		private float changeStateInterval = 5f;

		public override void Start()
		{
			((EnemyAI)this).Start();
			animator = ((Component)this).GetComponent<Animator>();
			navMeshAgent = ((Component)this).GetComponent<NavMeshAgent>();
			audioSource = ((Component)this).GetComponent<AudioSource>();
			if ((Object)(object)audioSource == (Object)null)
			{
				Debug.LogWarning((object)"AudioSource is missing from the enemy prefab");
			}
			else
			{
				audioSource.spatialBlend = 1f;
				audioSource.minDistance = 1f;
				audioSource.maxDistance = 20f;
				audioSource.rolloffMode = (AudioRolloffMode)0;
			}
			if ((Object)(object)mantle_footstep == (Object)null)
			{
				Debug.LogWarning((object)"mantle_footstep is not assigned in the inspector");
			}
			if ((Object)(object)mantle_roar == (Object)null)
			{
				Debug.LogWarning((object)"mantle_roar is not assigned in the inspector");
			}
			if ((Object)(object)roam_sound == (Object)null)
			{
				Debug.LogWarning((object)"roam_sound is not assigned in the inspector");
			}
			currentHealth = maxHealth;
			base.currentBehaviourStateIndex = 2;
			navMeshAgent.speed = normalSpeed;
			timer = wanderTimer;
			((MonoBehaviour)this).StartCoroutine(PlayRandomRoar());
		}

		public override void Update()
		{
			((EnemyAI)this).Update();
			if (base.isEnemyDead)
			{
				return;
			}
			if (isStunned)
			{
				if (!(Time.time >= stunEndTime))
				{
					navMeshAgent.speed = 0f;
					return;
				}
				isStunned = false;
				((EnemyAI)this).SwitchToBehaviourClientRpc(0);
			}
			if (currentHealth < healthThreshold && !isFleeing)
			{
				isFleeing = true;
				((EnemyAI)this).SwitchToBehaviourClientRpc(3);
			}
			int currentBehaviourStateIndex = base.currentBehaviourStateIndex;
			if (Time.time > lastStateChangeTime + changeStateInterval)
			{
				lastStateChangeTime = Time.time;
			}
			switch (currentBehaviourStateIndex)
			{
			case 1:
				HandleMovingTowardsPlayer();
				break;
			case 2:
				HandlePatrolling();
				break;
			case 3:
				HandleFleeing();
				break;
			default:
				navMeshAgent.speed = normalSpeed;
				animator.SetBool("isWalking", false);
				break;
			}
			if (knockbackApplied && currentBehaviourStateIndex != 1)
			{
				knockbackApplied = false;
			}
		}

		private void HandleMovingTowardsPlayer()
		{
			navMeshAgent.speed = (isCharging ? chargeSpeed : chaseSpeed);
			animator.SetBool("isCharging", isCharging);
			animator.SetBool("isWalking", !isCharging);
			animator.SetFloat("WalkSpeedMultiplier", isCharging ? 2f : 1f);
			footstepTimer += Time.deltaTime;
			if (footstepTimer >= footstepInterval / (isCharging ? 2f : 1f))
			{
				PlayMantleFootstep();
				footstepTimer = 0f;
			}
		}

		private void HandlePatrolling()
		{
			//IL_002f: 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_0047: Unknown result type (might be due to invalid IL or missing references)
			timer += Time.deltaTime;
			if (timer >= wanderTimer)
			{
				Vector3 destination = RandomNavSphere(((Component)this).transform.position, wanderRadius, -1);
				navMeshAgent.SetDestination(destination);
				timer = 0f;
			}
			if (!navMeshAgent.pathPending && navMeshAgent.remainingDistance < 0.5f)
			{
				timer = wanderTimer;
			}
			animator.SetBool("isWalking", true);
		}

		private void HandleFleeing()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: 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_0036: 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_0042: 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)
			//IL_004d: 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)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			navMeshAgent.speed = fleeSpeed;
			Vector3 val = ((Component)this).transform.position - ((Component)base.targetPlayer).transform.position;
			Vector3 normalized = ((Vector3)(ref val)).normalized;
			Vector3 position = ((Component)this).transform.position + normalized * 10f;
			SetDestinationToPosition(position);
			animator.SetBool("isWalking", true);
		}

		public static Vector3 RandomNavSphere(Vector3 origin, float dist, int layermask)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: 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_002a: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = Random.insideUnitSphere * dist;
			val += origin;
			NavMeshHit val2 = default(NavMeshHit);
			NavMesh.SamplePosition(val, ref val2, dist, layermask);
			return ((NavMeshHit)(ref val2)).position;
		}

		public void ApplyDamage(float damage)
		{
			currentHealth -= damage;
			if (currentHealth <= 0f)
			{
				Die();
			}
		}

		private void Die()
		{
			base.isEnemyDead = true;
			navMeshAgent.isStopped = true;
			animator.SetTrigger("Die");
		}

		private void OnTriggerEnter(Collider other)
		{
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: 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_00fb: 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)
			if (!((Component)other).CompareTag("Player") || !(Time.time > lastKnockbackTime + knockbackCooldownTime))
			{
				return;
			}
			Debug.Log((object)"Player or Obstacle Hit by Enemy!");
			isStunned = true;
			stunEndTime = Time.time + stunDuration;
			isCharging = false;
			animator.SetBool("isCharging", false);
			animator.SetTrigger("ChargeAtk");
			PlayRoamSound();
			navMeshAgent.speed = 0f;
			if (((Component)other).CompareTag("Player"))
			{
				PlayerControllerB component = ((Component)other).GetComponent<PlayerControllerB>();
				if ((Object)(object)component != (Object)null)
				{
					Vector3 val = ((Component)other).transform.position - ((Component)this).transform.position;
					Vector3 normalized = ((Vector3)(ref val)).normalized;
					((MonoBehaviour)this).StartCoroutine(ApplyKnockback(component, normalized));
					int num = (int)damageAmount;
					val = default(Vector3);
					component.DamagePlayer(num, true, true, (CauseOfDeath)0, 0, false, val);
				}
				knockbackApplied = true;
				lastKnockbackTime = Time.time;
			}
			((MonoBehaviour)this).StartCoroutine(TransitionToIdleAfterCharge());
		}

		private IEnumerator TransitionToIdleAfterCharge()
		{
			yield return (object)new WaitForSeconds(1f);
			animator.SetBool("isWalking", false);
			animator.SetBool("isCharging", false);
			animator.ResetTrigger("ChargeAtk");
			if (base.currentBehaviourStateIndex == 1)
			{
				isCharging = false;
				base.currentBehaviourStateIndex = 2;
			}
			((MonoBehaviour)this).StartCoroutine(RestartSearchingForPlayer());
		}

		private IEnumerator RestartSearchingForPlayer()
		{
			yield return (object)new WaitForSeconds(stunDuration);
			if (!base.isEnemyDead)
			{
				((EnemyAI)this).SwitchToBehaviourClientRpc(2);
			}
		}

		private IEnumerator ApplyKnockback(PlayerControllerB playerController, Vector3 hitDirection)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			((Behaviour)playerController).enabled = false;
			float knockbackForce = Random.Range(5f, 20f);
			float upwardsModifier = Random.Range(0.2f, 1f);
			Vector3 val = new Vector3(hitDirection.x, upwardsModifier, hitDirection.z);
			Vector3 force = ((Vector3)(ref val)).normalized * knockbackForce;
			CharacterController controller = ((Component)playerController).GetComponent<CharacterController>();
			if ((Object)(object)controller != (Object)null)
			{
				for (float timer = 0f; timer < 0.5f; timer += Time.deltaTime)
				{
					controller.Move(force * Time.deltaTime);
					yield return null;
				}
			}
			((Behaviour)playerController).enabled = true;
			RaycastHit hit = default(RaycastHit);
			if (Physics.Raycast(((Component)playerController).transform.position, ((Vector3)(ref force)).normalized, ref hit, 1f) && ((Component)((RaycastHit)(ref hit)).collider).gameObject.layer == LayerMask.NameToLayer("Default"))
			{
				controller.Move(Vector3.zero);
			}
		}

		public override void DoAIInterval()
		{
			//IL_007f: 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_00ac: Unknown result type (might be due to invalid IL or missing references)
			((EnemyAI)this).DoAIInterval();
			if (base.isEnemyDead || StartOfRound.Instance.allPlayersDead)
			{
				return;
			}
			switch (base.currentBehaviourStateIndex)
			{
			case 2:
				navMeshAgent.speed = normalSpeed;
				if (FoundClosestPlayerInRange(30f, 5f))
				{
					((EnemyAI)this).SwitchToBehaviourClientRpc(1);
				}
				break;
			case 1:
				if (!TargetClosestPlayerInAnyCase() || (Vector3.Distance(((Component)this).transform.position, ((Component)base.targetPlayer).transform.position) > 25f && !((EnemyAI)this).CheckLineOfSightForPosition(((Component)base.targetPlayer).transform.position, 45f, 60, -1f, (Transform)null)))
				{
					((EnemyAI)this).SwitchToBehaviourClientRpc(2);
				}
				else
				{
					MoveTowardsPlayer();
				}
				break;
			}
		}

		private bool FoundClosestPlayerInRange(float range, float senseRange)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			((EnemyAI)this).TargetClosestPlayer(1.5f, true, 70f);
			if ((Object)(object)base.targetPlayer == (Object)null)
			{
				((EnemyAI)this).TargetClosestPlayer(1.5f, false, 70f);
				range = senseRange;
			}
			return (Object)(object)base.targetPlayer != (Object)null && Vector3.Distance(((Component)this).transform.position, ((Component)base.targetPlayer).transform.position) < range;
		}

		private bool TargetClosestPlayerInAnyCase()
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			base.mostOptimalDistance = 2000f;
			base.targetPlayer = null;
			for (int i = 0; i < StartOfRound.Instance.connectedPlayersAmount + 1; i++)
			{
				float num = Vector3.Distance(((Component)this).transform.position, ((Component)StartOfRound.Instance.allPlayerScripts[i]).transform.position);
				if (num < base.mostOptimalDistance)
				{
					base.mostOptimalDistance = num;
					base.targetPlayer = StartOfRound.Instance.allPlayerScripts[i];
				}
			}
			return (Object)(object)base.targetPlayer != (Object)null;
		}

		private void MoveTowardsPlayer()
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)base.targetPlayer == (Object)null) && ((NetworkBehaviour)this).IsOwner)
			{
				SetDestinationToPosition(((Component)base.targetPlayer).transform.position, checkForPath: false);
				isCharging = true;
				animator.SetBool("isCharging", true);
				animator.SetBool("isWalking", false);
			}
		}

		private void SetDestinationToPosition(Vector3 position, bool checkForPath = true)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Expected O, but got Unknown
			//IL_0013: 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_0023: Invalid comparison between Unknown and I4
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			if (checkForPath)
			{
				NavMeshPath val = new NavMeshPath();
				if (navMeshAgent.CalculatePath(position, val) && (int)val.status == 0)
				{
					navMeshAgent.SetDestination(position);
				}
			}
			else
			{
				navMeshAgent.SetDestination(position);
			}
		}

		public void PlayMantleFootstep()
		{
			if ((Object)(object)audioSource != (Object)null && (Object)(object)mantle_footstep != (Object)null)
			{
				audioSource.PlayOneShot(mantle_footstep);
			}
			else
			{
				Debug.LogWarning((object)"AudioSource or FootstepClip is not assigned");
			}
		}

		public void PlayRoamSound()
		{
			if ((Object)(object)audioSource != (Object)null && (Object)(object)roam_sound != (Object)null)
			{
				audioSource.PlayOneShot(roam_sound);
			}
			else
			{
				Debug.LogWarning((object)"AudioSource or RoamClip is not assigned");
			}
		}

		private IEnumerator PlayRandomRoar()
		{
			while (!base.isEnemyDead)
			{
				float waitTime = Random.Range(10f, 20f);
				yield return (object)new WaitForSeconds(waitTime);
				PlayMantleRoar();
			}
		}

		public void PlayMantleRoar()
		{
			if ((Object)(object)audioSource != (Object)null && (Object)(object)mantle_roar != (Object)null)
			{
				audioSource.PlayOneShot(mantle_roar);
			}
			else
			{
				Debug.LogWarning((object)"AudioSource or RoarClip is not assigned");
			}
		}

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

		protected internal override string __getTypeName()
		{
			return "MantleEnemyAI";
		}
	}
	[BepInPlugin("Lembont.MantleEnemy", "MantleEnemy", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		internal static ManualLogSource Logger;

		public static AssetBundle? ModAssetss;

		internal static PluginConfig BoundConfig { get; private set; }

		private void Awake()
		{
			Logger = ((BaseUnityPlugin)this).Logger;
			BoundConfig = new PluginConfig(((BaseUnityPlugin)this).Config);
			InitializeNetworkBehaviours();
			string path = "MantleAssets!";
			ModAssetss = AssetBundle.LoadFromFile(Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), path));
			if ((Object)(object)ModAssetss == (Object)null)
			{
				Logger.LogError((object)"Failed to load custom assets.");
				return;
			}
			EnemyType val = ModAssetss.LoadAsset<EnemyType>("MantleEnemy");
			TerminalNode val2 = ModAssetss.LoadAsset<TerminalNode>("MantleEnemyTN");
			TerminalKeyword val3 = ModAssetss.LoadAsset<TerminalKeyword>("MantleEnemyTK");
			NetworkPrefabs.RegisterNetworkPrefab(val.enemyPrefab);
			Enemies.RegisterEnemy(val, BoundConfig.SpawnWeight.Value, (LevelTypes)(-1), val2, val3);
			Logger.LogInfo((object)"PLAY. PLAY BASEBALL WITH MANTLE. :3");
		}

		private static void InitializeNetworkBehaviours()
		{
			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 PluginInfo
	{
		public const string PLUGIN_GUID = "Lembont.MantleEnemy";

		public const string PLUGIN_NAME = "MantleEnemy";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}
namespace MantleEnemy.Configuration
{
	public class PluginConfig
	{
		public ConfigEntry<int> SpawnWeight;

		public PluginConfig(ConfigFile cfg)
		{
			SpawnWeight = cfg.Bind<int>("General", "Spawn weight", 60, "The spawn chance weight for ExampleEnemy, relative to other existing enemies.\nGoes up from 0, lower is more rare, 100 and up is very common.");
			ClearUnusedEntries(cfg);
		}

		private void ClearUnusedEntries(ConfigFile cfg)
		{
			PropertyInfo property = ((object)cfg).GetType().GetProperty("OrphanedEntries", BindingFlags.Instance | BindingFlags.NonPublic);
			Dictionary<ConfigDefinition, string> dictionary = (Dictionary<ConfigDefinition, string>)property.GetValue(cfg, null);
			dictionary.Clear();
			cfg.Save();
		}
	}
}
namespace Lembont.MantleEnemy.NetcodePatcher
{
	[AttributeUsage(AttributeTargets.Module)]
	internal class NetcodePatchedAssemblyAttribute : Attribute
	{
	}
}