Please disclose if your mod was created primarily using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Mantle v1.0.2
plugins/Mantle-Lembont/Lembont.MantleEnemy.dll
Decompiled 2 years agousing 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 { } }