Decompiled source of Dafis Monster Terry v1.0.1

BaseMonster.dll

Decompiled a month 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("BaseMonster")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Base Monster for Lethal Company")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("BaseMonster")]
[assembly: AssemblyTitle("BaseMonster")]
[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 MonsterMod.BaseMonster
{
	public class BaseMonster : EnemyAI
	{
		[Header("Detection Settings")]
		public float viewRadius = 15f;

		public float viewAngle = 90f;

		public LayerMask obstacleLayer;

		[Header("Movement Settings")]
		public float chaseSpeed = 4.5f;

		public float wanderSpeed = 2f;

		public float maxChaseDistance = 30f;

		public float loseTargetTime = 4f;

		[Header("Wander Settings")]
		public float wanderRadius = 10f;

		public float minWanderWaitTime = 2f;

		public float maxWanderWaitTime = 6f;

		[Header("Attack Settings")]
		public int damageAmount = 35;

		public float attackCooldown = 0.5f;

		public bool canKillPlayers = true;

		public AudioClip[] attackSounds;

		[Header("Collision Settings")]
		public float hitCooldown = 0.25f;

		private float timeSinceHittingPlayer;

		[Header("Audio")]
		public AudioSource monsterAudioSource;

		private Vector3 lastKnownPlayerPos;

		private float loseTargetTimer;

		private Vector3 wanderPoint;

		private Coroutine wanderRoutine;

		private bool canAttack = true;

		private float attackCooldownTimer;

		private ManualLogSource logger;

		public override void Start()
		{
			((EnemyAI)this).Start();
			logger = Logger.CreateLogSource("MonsterMod");
			logger.LogInfo((object)"Monster initialized");
			base.agent.speed = wanderSpeed;
			base.agent.angularSpeed = 120f;
			base.agent.acceleration = 8f;
			base.agent.stoppingDistance = 1f;
			CapsuleCollider component = ((Component)this).GetComponent<CapsuleCollider>();
			if ((Object)(object)component != (Object)null)
			{
				logger.LogInfo((object)$"Collider setup - isTrigger: {((Collider)component).isTrigger}, Layer: {LayerMask.LayerToName(((Component)component).gameObject.layer)}");
			}
			else
			{
				logger.LogError((object)"No CapsuleCollider found!");
			}
			if ((Object)(object)monsterAudioSource == (Object)null)
			{
				monsterAudioSource = ((Component)this).GetComponent<AudioSource>();
				if ((Object)(object)monsterAudioSource == (Object)null)
				{
					monsterAudioSource = ((Component)this).gameObject.AddComponent<AudioSource>();
				}
				monsterAudioSource.spatialBlend = 1f;
				monsterAudioSource.maxDistance = 15f;
				monsterAudioSource.rolloffMode = (AudioRolloffMode)1;
			}
		}

		public override void Update()
		{
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			((EnemyAI)this).Update();
			if (base.isEnemyDead || !base.ventAnimationFinished)
			{
				return;
			}
			timeSinceHittingPlayer += Time.deltaTime;
			if (!((NetworkBehaviour)this).IsServer)
			{
				return;
			}
			if (!canAttack)
			{
				attackCooldownTimer -= Time.deltaTime;
				if (attackCooldownTimer <= 0f)
				{
					canAttack = true;
				}
			}
			Vector3 velocity;
			switch (base.currentBehaviourStateIndex)
			{
			case 0:
				LookForPlayers();
				if ((Object)(object)base.creatureAnimator != (Object)null)
				{
					Animator creatureAnimator2 = base.creatureAnimator;
					velocity = base.agent.velocity;
					creatureAnimator2.SetBool("Moving", ((Vector3)(ref velocity)).magnitude > 0.1f);
				}
				break;
			case 1:
				UpdateChaseState();
				if ((Object)(object)base.creatureAnimator != (Object)null)
				{
					base.creatureAnimator.SetBool("Chasing", true);
					Animator creatureAnimator = base.creatureAnimator;
					velocity = base.agent.velocity;
					creatureAnimator.SetBool("Moving", ((Vector3)(ref velocity)).magnitude > 0.1f);
				}
				break;
			}
		}

		private void LookForPlayers()
		{
			//IL_0047: 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_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: 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_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: 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_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			if (!((NetworkBehaviour)this).IsServer)
			{
				return;
			}
			PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
			foreach (PlayerControllerB val in allPlayerScripts)
			{
				if ((Object)(object)val == (Object)null || !((Behaviour)val).isActiveAndEnabled || val.isPlayerDead)
				{
					continue;
				}
				float num = Vector3.Distance(((Component)this).transform.position, ((Component)val).transform.position);
				if (num <= viewRadius)
				{
					Vector3 val2 = ((Component)val).transform.position - ((Component)this).transform.position;
					Vector3 normalized = ((Vector3)(ref val2)).normalized;
					if (Vector3.Angle(((Component)this).transform.forward, normalized) < viewAngle / 2f && !Physics.Raycast(((Component)this).transform.position, normalized, num, LayerMask.op_Implicit(obstacleLayer)))
					{
						base.targetPlayer = val;
						lastKnownPlayerPos = ((Component)val).transform.position;
						StartChasing();
						break;
					}
				}
			}
		}

		private void StartChasing()
		{
			if (((NetworkBehaviour)this).IsServer)
			{
				StopWandering();
				base.agent.speed = chaseSpeed;
				loseTargetTimer = loseTargetTime;
				base.currentBehaviourStateIndex = 1;
				SyncBehaviourStateServerRpc(1);
			}
		}

		private void UpdateChaseState()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: 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)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: 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_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			if (!((NetworkBehaviour)this).IsServer || (Object)(object)base.targetPlayer == (Object)null)
			{
				return;
			}
			float num = Vector3.Distance(((Component)this).transform.position, ((Component)base.targetPlayer).transform.position);
			Vector3 val = ((Component)base.targetPlayer).transform.position - ((Component)this).transform.position;
			Vector3 normalized = ((Vector3)(ref val)).normalized;
			bool flag = false;
			if (num <= viewRadius && Vector3.Angle(((Component)this).transform.forward, normalized) < viewAngle / 2f && !Physics.Raycast(((Component)this).transform.position, normalized, num, LayerMask.op_Implicit(obstacleLayer)))
			{
				lastKnownPlayerPos = ((Component)base.targetPlayer).transform.position;
				loseTargetTimer = loseTargetTime;
				flag = true;
			}
			base.agent.SetDestination(lastKnownPlayerPos);
			if (!flag)
			{
				loseTargetTimer -= Time.deltaTime;
				if (loseTargetTimer <= 0f || num > maxChaseDistance)
				{
					StopChasing();
				}
			}
		}

		private void StopChasing()
		{
			if (((NetworkBehaviour)this).IsServer)
			{
				base.targetPlayer = null;
				base.agent.speed = wanderSpeed;
				base.currentBehaviourStateIndex = 0;
				if ((Object)(object)base.creatureAnimator != (Object)null)
				{
					base.creatureAnimator.SetBool("Chasing", false);
				}
				StartWandering();
				SyncBehaviourStateServerRpc(0);
			}
		}

		private void StartWandering()
		{
			if (wanderRoutine != null)
			{
				((MonoBehaviour)this).StopCoroutine(wanderRoutine);
			}
			wanderRoutine = ((MonoBehaviour)this).StartCoroutine(WanderRoutine());
		}

		private void StopWandering()
		{
			if (wanderRoutine != null)
			{
				((MonoBehaviour)this).StopCoroutine(wanderRoutine);
				wanderRoutine = null;
			}
		}

		private IEnumerator WanderRoutine()
		{
			while (base.currentBehaviourStateIndex == 0)
			{
				float num = Random.Range(minWanderWaitTime, maxWanderWaitTime);
				yield return (object)new WaitForSeconds(num);
				if (base.currentBehaviourStateIndex != 0)
				{
					break;
				}
				wanderPoint = GetRandomNavMeshPoint();
				base.agent.SetDestination(wanderPoint);
				while ((int)base.agent.pathStatus == 1 || base.agent.remainingDistance > base.agent.stoppingDistance)
				{
					if (base.currentBehaviourStateIndex != 0)
					{
						yield break;
					}
					yield return null;
				}
			}
		}

		private Vector3 GetRandomNavMeshPoint()
		{
			//IL_0000: 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)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: 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)
			Vector3 val = Random.insideUnitSphere * wanderRadius + ((Component)this).transform.position;
			Vector3 position = ((Component)this).transform.position;
			NavMeshHit val2 = default(NavMeshHit);
			if (NavMesh.SamplePosition(val, ref val2, wanderRadius, 1))
			{
				position = ((NavMeshHit)(ref val2)).position;
			}
			return position;
		}

		public override void OnCollideWithPlayer(Collider other)
		{
			((EnemyAI)this).OnCollideWithPlayer(other);
			logger.LogInfo((object)("Collision detected with: " + ((Object)((Component)other).gameObject).name));
			if (!((NetworkBehaviour)this).IsServer)
			{
				logger.LogInfo((object)"Not server, skipping collision");
				return;
			}
			if (base.isEnemyDead)
			{
				logger.LogInfo((object)"Enemy is dead, skipping collision");
				return;
			}
			if (timeSinceHittingPlayer < hitCooldown)
			{
				logger.LogInfo((object)$"Hit cooldown active: {timeSinceHittingPlayer}/{hitCooldown}");
				return;
			}
			PlayerControllerB val = ((EnemyAI)this).MeetsStandardPlayerCollisionConditions(other, false, false);
			if ((Object)(object)val == (Object)null)
			{
				logger.LogInfo((object)"Standard collision conditions not met");
				return;
			}
			if (val.isPlayerDead)
			{
				logger.LogInfo((object)"Player is dead, skipping damage");
				return;
			}
			logger.LogInfo((object)("Valid collision with player: " + val.playerUsername));
			timeSinceHittingPlayer = 0f;
			DamagePlayerServerRpc(((NetworkBehaviour)val).NetworkObjectId);
		}

		[ServerRpc(RequireOwnership = false)]
		private void HitPlayerServerRpc(int playerId)
		{
			logger.LogInfo((object)$"Server RPC: Hit player ID {playerId}");
			HitPlayerClientRpc(playerId);
		}

		[ClientRpc]
		private void HitPlayerClientRpc(int playerId)
		{
			logger.LogInfo((object)$"Client RPC: Processing hit effects for player {playerId}");
			if ((Object)(object)base.creatureAnimator != (Object)null)
			{
				base.creatureAnimator.SetTrigger("Attack");
			}
			if (attackSounds != null && attackSounds.Length != 0 && (Object)(object)monsterAudioSource != (Object)null)
			{
				AudioClip val = attackSounds[Random.Range(0, attackSounds.Length)];
				if ((Object)(object)val != (Object)null)
				{
					monsterAudioSource.PlayOneShot(val);
				}
			}
			timeSinceHittingPlayer = 0f;
		}

		private void AttackPlayer(PlayerControllerB player)
		{
			if (!canAttack)
			{
				logger.LogInfo((object)"Attack blocked by cooldown");
				return;
			}
			logger.LogInfo((object)$"Attacking player: {player.playerUsername} with damage: {damageAmount}");
			canAttack = false;
			attackCooldownTimer = attackCooldown;
			if ((Object)(object)base.creatureAnimator != (Object)null)
			{
				base.creatureAnimator.SetTrigger("Attack");
				logger.LogInfo((object)"Playing attack animation");
			}
			if (attackSounds != null && attackSounds.Length != 0)
			{
				PlayAttackSoundServerRpc();
				logger.LogInfo((object)"Playing attack sound");
			}
			logger.LogInfo((object)$"Sending damage ServerRpc for player NetworkId: {((NetworkBehaviour)player).NetworkObjectId}");
			DamagePlayerServerRpc(((NetworkBehaviour)player).NetworkObjectId);
		}

		[ServerRpc(RequireOwnership = false)]
		private void DamagePlayerServerRpc(ulong playerObjectId)
		{
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			logger.LogInfo((object)$"DamagePlayerServerRpc called for ID: {playerObjectId}");
			if (!NetworkManager.Singleton.SpawnManager.SpawnedObjects.ContainsKey(playerObjectId))
			{
				logger.LogError((object)$"Could not find player with ID: {playerObjectId}");
				return;
			}
			PlayerControllerB component = ((Component)NetworkManager.Singleton.SpawnManager.SpawnedObjects[playerObjectId]).GetComponent<PlayerControllerB>();
			if ((Object)(object)component == (Object)null)
			{
				logger.LogError((object)"PlayerControllerB not found on NetworkObject");
				return;
			}
			component.DamagePlayer(damageAmount, true, true, (CauseOfDeath)4, 0, false, default(Vector3));
			DamagePlayerClientRpc(playerObjectId);
		}

		[ClientRpc]
		private void DamagePlayerClientRpc(ulong playerObjectId)
		{
			logger.LogInfo((object)$"DamagePlayerClientRpc processing for ID: {playerObjectId}");
			if ((Object)(object)base.creatureAnimator != (Object)null)
			{
				base.creatureAnimator.SetTrigger("Attack");
			}
			if (attackSounds != null && attackSounds.Length != 0 && (Object)(object)monsterAudioSource != (Object)null)
			{
				AudioClip val = attackSounds[Random.Range(0, attackSounds.Length)];
				monsterAudioSource.PlayOneShot(val);
			}
			if (NetworkManager.Singleton.SpawnManager.SpawnedObjects.ContainsKey(playerObjectId))
			{
				PlayerControllerB component = ((Component)NetworkManager.Singleton.SpawnManager.SpawnedObjects[playerObjectId]).GetComponent<PlayerControllerB>();
				if ((Object)(object)component != (Object)null && (Object)(object)component.playerBodyAnimator != (Object)null)
				{
					component.playerBodyAnimator.SetTrigger("Hit");
				}
			}
		}

		[ServerRpc]
		private void PlayAttackSoundServerRpc()
		{
			PlayAttackSoundClientRpc();
		}

		[ClientRpc]
		private void PlayAttackSoundClientRpc()
		{
			if (attackSounds != null && attackSounds.Length != 0 && (Object)(object)monsterAudioSource != (Object)null)
			{
				AudioClip val = attackSounds[Random.Range(0, attackSounds.Length)];
				if ((Object)(object)val != (Object)null)
				{
					monsterAudioSource.PlayOneShot(val);
				}
			}
		}

		[ServerRpc]
		private void SyncBehaviourStateServerRpc(int newState)
		{
			base.currentBehaviourStateIndex = newState;
			SyncBehaviourStateClientRpc(newState);
		}

		[ClientRpc]
		private void SyncBehaviourStateClientRpc(int newState)
		{
			base.currentBehaviourStateIndex = newState;
			if ((Object)(object)base.creatureAnimator != (Object)null)
			{
				base.creatureAnimator.SetBool("Chasing", newState == 1);
			}
		}

		public override void KillEnemy(bool destroy = false)
		{
			((EnemyAI)this).KillEnemy(destroy);
			((MonoBehaviour)this).StopAllCoroutines();
		}
	}
}