using Characters.Enemy.States; using Koptilnya.StateMachine; using Mirror; using UnityEngine; using UnityEngine.AI; using UnityEngine.Animations.Rigging; using UnityEngine.Serialization; namespace Characters.Enemy { public class Enemy : Pawn { public NavMeshAgent agent; public Animator animator; public Rig aimRig; public AudioSource audioSource; public ParticleSystem hitVFX; public Transform aimTransform; public float aggressionDistance = 5f; [HideInInspector] public bool canAttack; [SyncVar] public EnemyState state = EnemyState.Idle; [SyncVar, HideInInspector] public float aimRigWeight; public readonly StateMachine stateMachine = new StateMachine(); [FormerlySerializedAs("target")] public Transform targetTransform; public NetworkAnimator networkAnimator; public float DistanceToTarget => Vector3.Distance(targetTransform.transform.position, transform.position); private CustomNetworkManager _networkManager; private NetworkGameManager _networkGameManager; private float _targetAimRigWeight; private float _stepCycle; private AudioClip _footstepClip; private const float StepDelay = 0.15f; private const float RunSpeed = 4.974f; private static readonly int SpeedAnimHash = Animator.StringToHash("speed"); void Start() { _networkManager = NetworkManager.singleton.GetComponent(); _networkGameManager = NetworkGameManager.singleton; networkAnimator = GetComponent(); _footstepClip = Resources.Load("Audio/EnemySounds/Steps/monsterStep1"); stateMachine.Add(new IdleState(this)); stateMachine.Add(new PatrolState(this)); stateMachine.Add(new ChaseState(this)); stateMachine.Add(new StunnedState(this)); stateMachine.Add(new AttackState(this)); stateMachine.SetCurrentState(state); } void Update() { Footsteps(); if (isServer) { agent.speed = _speedMul * RunSpeed; animator.SetFloat(SpeedAnimHash, agent.velocity.magnitude); } aimRigWeight = isServer ? Mathf.Lerp(aimRigWeight, _targetAimRigWeight, Time.deltaTime) : aimRigWeight; aimRig.weight = aimRigWeight; stateMachine.Update(); } void FixedUpdate() { stateMachine.FixedUpdate(); } public void SetAimRigWeight(float value) { _targetAimRigWeight = value; } void Footsteps() { // float velocity = ((_position - transform.position) / Time.deltaTime).magnitude; float velocity = 0; float clampedVelocity = Mathf.Clamp(RunSpeed / velocity + 1, 1, RunSpeed); if (Time.time > _stepCycle && velocity > 0) { audioSource.pitch = 1f + Random.Range(-0.1f, 0.1f); audioSource.PlayOneShot(_footstepClip); _stepCycle = Time.time + (clampedVelocity * StepDelay); } } [ClientRpc] public void RpcKillTarget(Transform target) { Interactions interactions = target.GetComponent(); if (interactions != null) interactions.DropProp(); target.GetComponent().Die(); } [ServerCallback] public override void TakeDamage() { base.TakeDamage(); ChangeState(EnemyState.Stunned); } public void ChangeState(EnemyState newState) { state = newState; stateMachine.SetCurrentState(newState); } public Transform GetClosestTarget() { var alivePlayers = _networkManager.alive; if (targetTransform != null && alivePlayers.Count == 1 && alivePlayers[0].transform == targetTransform) { return targetTransform; } Transform closestTarget = null; float sortDistance = float.MaxValue; foreach (var player in _networkManager.alive) { float distance = Vector3.Distance(player.transform.position, transform.position); if (distance <= aggressionDistance && distance < sortDistance && agent.SetDestination(player.transform.position)) { sortDistance = distance; closestTarget = player.transform; } } return closestTarget; } } }