Decompiled source of Dafis Monster Egg Pawn v1.0.0

EggPawn.dll

Decompiled 3 hours ago
using System;
using System.Collections;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx.Logging;
using GameNetcodeStuff;
using Microsoft.CodeAnalysis;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.AI;

[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("EggPawn")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("EggPawn Monster for Lethal Company")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("EggPawn")]
[assembly: AssemblyTitle("EggPawn")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.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 EggPawnMod
{
	public class EggPawnAI : EnemyAI
	{
		[Header("Movement Settings")]
		public float moveSpeed = 4f;

		public float pursuitTime = 5f;

		public float minIdleTime = 2f;

		public float maxIdleTime = 5f;

		[Header("Health Settings")]
		public int maxHealth = 3;

		private bool isDying;

		[Header("Detection Settings")]
		public float detectionRadius = 15f;

		public LayerMask detectionMask;

		[Header("Animation Settings")]
		public string idleAnimationTrigger = "Idle";

		public string moveAnimationTrigger = "Moving";

		public string detectAnimationTrigger = "Alert";

		public string deathAnimationTrigger = "Death";

		[Header("Audio Settings")]
		public AudioClip detectionSound;

		public AudioClip[] movementSounds;

		public float movementSoundInterval = 0.5f;

		public AudioClip deathSound;

		public AudioClip explosionSound;

		[Header("Death Settings")]
		public GameObject explosionEffectPrefab;

		public EnemyType[] possibleSpawns;

		public Item[] possibleScrap;

		private Vector3 targetLocation;

		private bool isPursuing;

		private float pursuitTimer;

		private float idleTimer;

		private float timeSinceLastStep;

		private bool hasInitialDestination;

		private bool isIdle = true;

		private float timeSinceHittingPlayer;

		private bool hasDetectedPlayer;

		private PlayerControllerB lastDetectedPlayer;

		private ManualLogSource logger;

		public override void Start()
		{
			((EnemyAI)this).Start();
			logger = Logger.CreateLogSource("EggPawnMod");
			logger.LogInfo((object)"EggPawn initialized");
			base.enemyHP = maxHealth;
			if ((Object)(object)base.creatureSFX == (Object)null)
			{
				base.creatureSFX = ((Component)this).gameObject.AddComponent<AudioSource>();
				base.creatureSFX.spatialBlend = 1f;
				base.creatureSFX.maxDistance = 15f;
				base.creatureSFX.rolloffMode = (AudioRolloffMode)1;
			}
			base.agent.speed = moveSpeed;
			base.agent.stoppingDistance = 0.5f;
			base.agent.angularSpeed = 120f;
			idleTimer = Random.Range(minIdleTime, maxIdleTime);
			if (((NetworkBehaviour)this).IsServer)
			{
				((MonoBehaviour)this).StartCoroutine(SetInitialDestination());
			}
		}

		private IEnumerator SetInitialDestination()
		{
			yield return (object)new WaitForSeconds(1f);
			SetNewRandomDestination();
			hasInitialDestination = true;
			logger.LogInfo((object)"Initial destination set");
		}

		public override void Update()
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: 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)
			((EnemyAI)this).Update();
			if (!((NetworkBehaviour)this).IsServer || base.isEnemyDead || !hasInitialDestination)
			{
				return;
			}
			timeSinceHittingPlayer += Time.deltaTime;
			PlayerControllerB val = ScanForPlayers();
			if ((Object)(object)val != (Object)null && !isPursuing)
			{
				StartPursuit(((Component)val).transform.position);
			}
			if (isPursuing)
			{
				HandlePursuit();
			}
			else
			{
				HandleIdle();
			}
			Vector3 velocity = base.agent.velocity;
			if (((Vector3)(ref velocity)).magnitude > 0.1f)
			{
				timeSinceLastStep += Time.deltaTime;
				if (timeSinceLastStep >= movementSoundInterval)
				{
					PlayMovementSoundServerRpc();
					timeSinceLastStep = 0f;
				}
			}
			UpdateAnimationState();
		}

		private PlayerControllerB ScanForPlayers()
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
			foreach (PlayerControllerB val in allPlayerScripts)
			{
				if ((Object)(object)val == (Object)null || val.isPlayerDead || !((Behaviour)val).isActiveAndEnabled)
				{
					continue;
				}
				float num = Vector3.Distance(((Component)this).transform.position, ((Component)val).transform.position);
				if (num <= detectionRadius)
				{
					Vector3 val2 = ((Component)val).transform.position - ((Component)this).transform.position;
					Vector3 normalized = ((Vector3)(ref val2)).normalized;
					if (!Physics.Raycast(((Component)this).transform.position, normalized, num, LayerMask.op_Implicit(detectionMask)))
					{
						logger.LogInfo((object)("Detected player: " + val.playerUsername));
						return val;
					}
				}
			}
			return null;
		}

		public override void HitEnemy(int force = 1, PlayerControllerB playerWhoHit = null, bool playHitSFX = false, int hitID = -1)
		{
			((EnemyAI)this).HitEnemy(force, playerWhoHit, playHitSFX, hitID);
			logger.LogInfo((object)$"EggPawn hit for {force} damage. Current HP: {base.enemyHP}");
			if (isDying)
			{
				return;
			}
			base.enemyHP -= force;
			if (base.enemyHP <= 0 && !base.isEnemyDead)
			{
				logger.LogInfo((object)"EggPawn health depleted, triggering death");
				if (((NetworkBehaviour)this).IsServer)
				{
					((EnemyAI)this).KillEnemyOnOwnerClient(false);
				}
				else
				{
					KillEnemyServerRpc();
				}
			}
			else
			{
				PlayHitEffectsServerRpc();
			}
		}

		private void HandlePursuit()
		{
			pursuitTimer -= Time.deltaTime;
			if (pursuitTimer <= 0f || (base.agent.remainingDistance <= base.agent.stoppingDistance && !base.agent.pathPending))
			{
				EndPursuit();
			}
		}

		private void HandleIdle()
		{
			if (!(base.agent.remainingDistance <= base.agent.stoppingDistance) || base.agent.pathPending)
			{
				return;
			}
			if (!isIdle)
			{
				isIdle = true;
				idleTimer = Random.Range(minIdleTime, maxIdleTime);
				return;
			}
			idleTimer -= Time.deltaTime;
			if (idleTimer <= 0f)
			{
				SetNewRandomDestination();
			}
		}

		private void StartPursuit(Vector3 playerPosition)
		{
			//IL_000b: 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_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			logger.LogInfo((object)$"Starting pursuit to position: {playerPosition}");
			targetLocation = playerPosition;
			pursuitTimer = pursuitTime;
			isPursuing = true;
			isIdle = false;
			base.agent.SetDestination(targetLocation);
			base.creatureAnimator.SetTrigger(detectAnimationTrigger);
			if ((Object)(object)detectionSound != (Object)null)
			{
				base.creatureSFX.PlayOneShot(detectionSound);
				WalkieTalkie.TransmitOneShotAudio(base.creatureSFX, detectionSound, 1f);
			}
			PlayDetectionEffectsServerRpc();
		}

		private void EndPursuit()
		{
			logger.LogInfo((object)"Ending pursuit");
			isPursuing = false;
			hasDetectedPlayer = false;
			lastDetectedPlayer = null;
			pursuitTimer = 0f;
			SetNewRandomDestination();
		}

		private void UpdateAnimationState()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			Vector3 velocity = base.agent.velocity;
			bool flag = ((Vector3)(ref velocity)).magnitude > 0.1f;
			base.creatureAnimator.SetBool(moveAnimationTrigger, flag);
			if (!flag && !isPursuing)
			{
				base.creatureAnimator.SetTrigger(idleAnimationTrigger);
			}
		}

		private void SetNewRandomDestination()
		{
			//IL_000a: 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_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			if (((NetworkBehaviour)this).IsServer)
			{
				Vector3 randomNavMeshPoint = GetRandomNavMeshPoint();
				base.agent.SetDestination(randomNavMeshPoint);
				isIdle = false;
				logger.LogInfo((object)$"Set new random destination: {randomNavMeshPoint}");
			}
		}

		private Vector3 GetRandomNavMeshPoint()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: 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_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: 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)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = Random.insideUnitSphere * 20f + ((Component)this).transform.position;
			Vector3 position = ((Component)this).transform.position;
			NavMeshHit val2 = default(NavMeshHit);
			if (NavMesh.SamplePosition(val, ref val2, 20f, -1))
			{
				position = ((NavMeshHit)(ref val2)).position;
			}
			return position;
		}

		public override void OnCollideWithPlayer(Collider other)
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			if (!((NetworkBehaviour)this).IsServer || base.isEnemyDead || timeSinceHittingPlayer < 0.5f)
			{
				return;
			}
			PlayerControllerB val = ((EnemyAI)this).MeetsStandardPlayerCollisionConditions(other, false, false);
			if (!((Object)(object)val == (Object)null) && !val.isPlayerDead)
			{
				timeSinceHittingPlayer = 0f;
				if ((Object)(object)val == (Object)(object)GameNetworkManager.Instance.localPlayerController)
				{
					val.DamagePlayer(35, true, true, (CauseOfDeath)1, 0, false, default(Vector3));
				}
				HitPlayerServerRpc(((NetworkBehaviour)val).NetworkObjectId);
			}
		}

		public override void KillEnemy(bool destroy = false)
		{
			if (!base.isEnemyDead && !isDying)
			{
				logger.LogInfo((object)"EggPawn killed");
				isDying = true;
				base.isEnemyDead = true;
				((MonoBehaviour)this).StopAllCoroutines();
				if (base.agent.isOnNavMesh)
				{
					base.agent.isStopped = true;
				}
				base.creatureAnimator.SetTrigger(deathAnimationTrigger);
				((MonoBehaviour)this).StartCoroutine(DeathSequence());
			}
		}

		private IEnumerator DeathSequence()
		{
			PlayDeathEffectsServerRpc();
			yield return (object)new WaitForSeconds(1f);
			if (((NetworkBehaviour)this).IsServer)
			{
				if (Random.value < 0.5f && possibleSpawns.Length != 0)
				{
					EnemyType val = possibleSpawns[Random.Range(0, possibleSpawns.Length)];
					RoundManager.Instance.SpawnEnemyGameObject(((Component)this).transform.position, 0f, -1, val);
				}
				else if (possibleScrap.Length != 0)
				{
					Object.Instantiate<GameObject>(possibleScrap[Random.Range(0, possibleScrap.Length)].spawnPrefab, ((Component)this).transform.position + Vector3.up * 0.5f, Quaternion.identity).GetComponent<NetworkObject>().Spawn(false);
				}
			}
			yield return (object)new WaitForSeconds(0.5f);
			if ((Object)(object)explosionEffectPrefab != (Object)null)
			{
				Object.Instantiate<GameObject>(explosionEffectPrefab, ((Component)this).transform.position, Quaternion.identity);
			}
			if (((NetworkBehaviour)this).IsServer)
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
			}
		}

		[ServerRpc]
		private void PlayDetectionEffectsServerRpc()
		{
			PlayDetectionEffectsClientRpc();
		}

		[ClientRpc]
		private void PlayDetectionEffectsClientRpc()
		{
			if (!((NetworkBehaviour)this).IsOwner && (Object)(object)detectionSound != (Object)null)
			{
				base.creatureSFX.PlayOneShot(detectionSound);
			}
		}

		[ServerRpc]
		private void PlayMovementSoundServerRpc()
		{
			PlayMovementSoundClientRpc();
		}

		[ClientRpc]
		private void PlayMovementSoundClientRpc()
		{
			if (movementSounds != null && movementSounds.Length != 0)
			{
				base.creatureSFX.PlayOneShot(movementSounds[Random.Range(0, movementSounds.Length)]);
			}
		}

		[ServerRpc(RequireOwnership = false)]
		private void KillEnemyServerRpc()
		{
			if (!base.isEnemyDead)
			{
				((EnemyAI)this).KillEnemy(false);
			}
		}

		[ServerRpc]
		private void PlayHitEffectsServerRpc()
		{
			PlayHitEffectsClientRpc();
		}

		[ClientRpc]
		private void PlayHitEffectsClientRpc()
		{
			if ((Object)(object)base.creatureAnimator != (Object)null)
			{
				base.creatureAnimator.SetTrigger("Hit");
			}
			_ = (Object)(object)base.creatureSFX != (Object)null;
		}

		[ServerRpc]
		private void PlayDeathEffectsServerRpc()
		{
			PlayDeathEffectsClientRpc();
		}

		[ClientRpc]
		private void PlayDeathEffectsClientRpc()
		{
			//IL_0058: 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)
			if ((Object)(object)deathSound != (Object)null)
			{
				base.creatureSFX.PlayOneShot(deathSound);
			}
			if ((Object)(object)explosionSound != (Object)null)
			{
				base.creatureSFX.PlayOneShot(explosionSound);
			}
			if ((Object)(object)explosionEffectPrefab != (Object)null)
			{
				Object.Instantiate<GameObject>(explosionEffectPrefab, ((Component)this).transform.position, Quaternion.identity);
			}
		}

		[ServerRpc]
		private void HitPlayerServerRpc(ulong playerObjectId)
		{
			HitPlayerClientRpc(playerObjectId);
		}

		[ClientRpc]
		private void HitPlayerClientRpc(ulong playerObjectId)
		{
			PlayerControllerB val = default(PlayerControllerB);
			if (NetworkManager.Singleton.SpawnManager.SpawnedObjects.TryGetValue(playerObjectId, out var value) && ((Component)value).TryGetComponent<PlayerControllerB>(ref val) && (Object)(object)val.playerBodyAnimator != (Object)null)
			{
				val.playerBodyAnimator.SetTrigger("Hit");
			}
		}
	}
}