2024-03-19 21:38:59 +03:00

151 lines
4.8 KiB
C#

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<EnemyState> stateMachine = new StateMachine<EnemyState>();
[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<CustomNetworkManager>();
_networkGameManager = NetworkGameManager.singleton;
networkAnimator = GetComponent<NetworkAnimator>();
_footstepClip = Resources.Load<AudioClip>("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<Interactions>();
if (interactions != null) interactions.DropProp();
target.GetComponent<Pawn>().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;
}
}
}