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();
}
}
}