ProjectZ/Assets/Scripts/Characters/Enemy/EnemyController.cs
2024-02-19 21:00:36 +03:00

366 lines
11 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
using Mirror;
using UnityEngine.Animations.Rigging;
using Player;
public partial class EnemyController : Pawn
{
public bool spawnCube = false;
public NavMeshAgent controller;
public Animator animator;
public Rig targetLayer;
public AudioSource audioSource;
public ParticleSystem hitVFX;
public bool hasPath;
public GameObject propPrefab;
public Transform aimTarget;
public float aggressionDistance = 5f;
public float _stepTiming = 0.15f;
CustomNetworkManager networkManager;
NetworkGameManager networkGameManager;
private Transform _target = null;
private List<Pawn> players;
private Vector3 _position;
private float _stepCycle;
private float _runSpeed = 4.974f; //_walkSpeed = 0.299f
private float targetLayerWeight;
private int _currenPointId;
[SyncVar]
private float layerWeight;
private float _remainingDistance;
NavMeshTriangulation navMeshData;
[SyncVar(hook = nameof(OnStateChanged))]
private ENEMY_STATE state = ENEMY_STATE.PATROL;
private AudioClip skrClip, agressiveClip;
void Start()
{
// Time.timeScale = 10;
skrClip = Resources.Load<AudioClip>("Audio/EnemySounds/woodSkr");
agressiveClip = Resources.Load<AudioClip>("Audio/EnemySounds/FX/agressive2");
networkManager = NetworkManager.singleton.GetComponent<CustomNetworkManager>();
networkGameManager = NetworkGameManager.singleton;
players = networkManager.alive;
if (!isServer) return;
this.OnDamage += TakeDamageAnimation;
navMeshData = NavMesh.CalculateTriangulation();
if (spawnCube)
{
Vector3 randLoc = navMeshData.vertices[navMeshData.indices[Random.Range(0, navMeshData.indices.Length - 3)]];
GameObject gameObject = Instantiate(propPrefab, randLoc + Vector3.up * 1, Quaternion.identity);
gameObject.GetComponent<PropBehaviour>().Original = true;
NetworkServer.Spawn(gameObject);
}
navMeshPath = new NavMeshPath();
}
public NavMeshPath navMeshPath;
public bool isKilling = false;
void Update()
{
controller.speed = _speedMul * _runSpeed;
CalculateFootstepTriggers();
layerWeight = isServer ? Mathf.Lerp(layerWeight, targetLayerWeight, Time.deltaTime) : layerWeight;
targetLayer.weight = layerWeight;
if (!isServer) return;
animator.SetFloat("speed", controller.velocity.magnitude);
_remainingDistance = controller.GetPathRemainingDistance();
hasPath = controller.pathStatus != NavMeshPathStatus.PathComplete;
// Есть таргет?
if (_target != null) // Да
{
controller.destination = _target.position;
float distance = Vector3.Distance(_target.transform.position, transform.position);
if (distance < aggressionDistance) // (_remainingDistance < aggressionDistance && _remainingDistance > 0)
{
aimTarget.position = _target.position + _target.up * 1.2f;
targetLayerWeight = 1f;
// Debug.Log(_remainingDistance);
// Если подошли к нему
if (distance < 1f)
{
// Debug.Log("da");
// _target.GetComponent<Interactions>().DropProp();
if (isKilling == false)
{
RpcKillPlayer(_target);
animator.SetTrigger("attack");
StartCoroutine(AfterKillTimer());
}
isKilling = true;
}
}
else
{
_target = null;
}
}
else
{
//if (controller.GetPathRemainingDistance() <= 0f) // Нет mojet doiti
targetLayerWeight = 0f;
// Ищем ближайшего игрока
foreach (var player in players)
{
float distance = Vector3.Distance(player.transform.position, transform.position);
// Debug.Log(CalculateNewPath(player.transform));
if (distance <= aggressionDistance && CalculateNewPath(player.transform)) // && _remainingDistance > 0
{
//if (_remainingDistance < aggressionDistance && controller.GetPathRemainingDistance() >= 0)
_target = player.transform;
break;
}
}
if (_target == null && _remainingDistance <= 1.5f) //!controller.pathPending ||
{
SetRandomDestination();
}
}
// if (_target == null)
// {
// float pointDistance = Vector3.Distance(_patrolPoints[_currenPointId].position, transform.position);
// if (pointDistance < 2)
// {
// _currenPointId = Random.Range(0, _patrolPoints.Length);
// }
// controller.destination = _patrolPoints[_currenPointId].position;
// foreach (var player in players)
// {
// float distance = Vector3.Distance(player.transform.position, transform.position);
// if (distance < aggressionDistance)
// {
// state = ENEMY_STATE.ROTATE;
// _target = player.transform;
// targetLayerWeight = 1f;
// break;
// }
// }
// }
// else
// {
// if (layerWeight >= 0.9f && hasPath)
// {
// if (state == ENEMY_STATE.ROTATE)
// {
// state = ENEMY_STATE.CHASE;
// }
// controller.destination = _target.position;
// }
// if (controller.velocity.magnitude <= 1 && !hasPath)
// {
// _target = null;
// state = ENEMY_STATE.PATROL;
// }
// target.position = _target.position + _target.up * 1.2f;
// var distance = Vector3.Distance(_target.transform.position, transform.position);
// if (distance <= 1)
// {
// _target.GetComponent<Pawn>().Die();
// }
// if (distance >= aggressionDistance)
// {
// state = ENEMY_STATE.PATROL;
// _target = null;
// targetLayerWeight = 0f;
// }
// }
}
bool CalculateNewPath(Transform target)
{
controller.CalculatePath(target.position, navMeshPath);
if (navMeshPath.status != NavMeshPathStatus.PathComplete)
{
return false;
}
else
{
return true;
}
}
[ClientRpc]
void RpcKillPlayer(Transform target)
{
Interactions interactions = target.GetComponent<Interactions>();
if (interactions != null) interactions.DropProp();
target.GetComponent<Pawn>().Die();
}
IEnumerator AfterKillTimer()
{
yield return new WaitForSeconds(5);
isKilling = false;
_target = null;
aimTarget.position = transform.position;
SetRandomDestination();
}
[Server]
void SetRandomDestination()
{
var targetPoint = GetRandomLocation();
// var targetPoint = navMeshData.vertices[2000];
//_patrolPoints[Random.Range(0, _patrolPoints.Length - 1)].position;
// hasPath = controller.SetDestination(targetPoint);
controller.destination = targetPoint;
// hasPath = controller.hasPath;
}
void OnStateChanged(ENEMY_STATE oldState, ENEMY_STATE newState)
{
audioSource.Stop();
switch (newState)
{
case ENEMY_STATE.PATROL:
audioSource.reverbZoneMix = 1f;
break;
case ENEMY_STATE.ROTATE:
audioSource.clip = skrClip;
audioSource.Play();
break;
case ENEMY_STATE.CHASE:
// audioSource.clip = agressiveClip;
// audioSource.reverbZoneMix = 0f;
// audioSource.Play();
break;
}
}
private List<Vector3> _points = new List<Vector3>();
Vector3 GetRandomLocation()
{
// // NavMeshTriangulation navMeshData = NavMesh.CalculateTriangulation();
// int maxIndices = navMeshData.indices.Length - 3;
// // Pick the first indice of a random triangle in the nav mesh
// int firstVertexSelected = Random.Range(0, maxIndices);
// int secondVertexSelected = Random.Range(0, maxIndices);
// //Spawn on Verticies
// Vector3 point = navMeshData.vertices[navMeshData.indices[firstVertexSelected]];
// Vector3 firstVertexPosition = navMeshData.vertices[navMeshData.indices[firstVertexSelected]];
// Vector3 secondVertexPosition = navMeshData.vertices[navMeshData.indices[secondVertexSelected]];
// //Eliminate points that share a similar X or Z position to stop spawining in square grid line formations
// if ((int)firstVertexPosition.x == (int)secondVertexPosition.x ||
// (int)firstVertexPosition.z == (int)secondVertexPosition.z
// )
// {
// point = GetRandomLocation(); //Re-Roll a position - I'm not happy with this recursion it could be better
// }
// else
// {
// // Select a random point on it
// point = Vector3.Lerp(
// firstVertexPosition,
// secondVertexPosition, //[t + 1]],
// Random.Range(0.05f, 0.95f) // Not using Random.value as clumps form around Verticies
// );
// }
// //Vector3.Lerp(point, navMeshData.vertices[navMeshData.indices[t + 2]], Random.value); //Made Obsolete
// return point;
var point = navMeshData.vertices[navMeshData.indices[Random.Range(0, navMeshData.indices.Length - 3)]];
_points.Add(point);
return point;
}
void OnDrawGizmos()
{
foreach (var point in _points)
{
Gizmos.DrawSphere(point, 1f);
}
}
void CalculateFootstepTriggers()
{
float _velocity = ((_position - transform.position) / Time.deltaTime).magnitude;
// Debug.Log(_controllerVelocity);
float clampedVelocity = Mathf.Clamp(_runSpeed / _velocity + 1, 1, _runSpeed);
if (Time.time > _stepCycle && _velocity > 0)
{
CallFootstepClip();
_stepCycle = Time.time + (clampedVelocity * _stepTiming);
}
_position = transform.position;
}
public void CallFootstepClip()
{
audioSource.pitch = 1f + Random.Range(-0.1f, 0.1f);
audioSource.PlayOneShot(Resources.Load<AudioClip>("Audio/EnemySounds/Steps/monsterStep1"));
}
void TakeDamageAnimation(Pawn self)
{
animator.SetTrigger("damage");
hitVFX.Stop();
hitVFX.Play();
}
}