2024-02-19 21:00:36 +03:00
|
|
|
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;
|
2024-03-17 00:00:54 +03:00
|
|
|
|
2024-02-19 21:00:36 +03:00
|
|
|
private AudioClip skrClip, agressiveClip;
|
2024-03-17 00:00:54 +03:00
|
|
|
public NavMeshPath navMeshPath;
|
|
|
|
public bool isKilling = false;
|
|
|
|
[SerializeField] private bool canAttack = true;
|
2024-03-17 01:22:01 +03:00
|
|
|
|
2024-02-19 21:00:36 +03:00
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
2024-03-17 01:22:01 +03:00
|
|
|
// if (controller.pathStatus == NavMeshPathStatus.PathComplete && !controller.pathPending && _target != null)
|
|
|
|
// {
|
|
|
|
// _target = null;
|
|
|
|
// }
|
|
|
|
|
2024-02-19 21:00:36 +03:00
|
|
|
// Есть таргет?
|
|
|
|
if (_target != null) // Да
|
|
|
|
{
|
|
|
|
controller.destination = _target.position;
|
|
|
|
|
|
|
|
float distance = Vector3.Distance(_target.transform.position, transform.position);
|
|
|
|
|
2024-03-17 01:22:01 +03:00
|
|
|
if (distance < aggressionDistance)
|
2024-02-19 21:00:36 +03:00
|
|
|
{
|
|
|
|
aimTarget.position = _target.position + _target.up * 1.2f;
|
|
|
|
targetLayerWeight = 1f;
|
2024-03-17 01:22:01 +03:00
|
|
|
|
2024-02-19 21:00:36 +03:00
|
|
|
if (distance < 1f)
|
|
|
|
{
|
2024-03-17 00:00:54 +03:00
|
|
|
if (canAttack && !isKilling)
|
2024-02-19 21:00:36 +03:00
|
|
|
{
|
|
|
|
RpcKillPlayer(_target);
|
|
|
|
animator.SetTrigger("attack");
|
|
|
|
|
|
|
|
StartCoroutine(AfterKillTimer());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
_target = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
targetLayerWeight = 0f;
|
|
|
|
// Ищем ближайшего игрока
|
|
|
|
foreach (var player in players)
|
|
|
|
{
|
|
|
|
float distance = Vector3.Distance(player.transform.position, transform.position);
|
|
|
|
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CalculateNewPath(Transform target)
|
|
|
|
{
|
|
|
|
controller.CalculatePath(target.position, navMeshPath);
|
|
|
|
|
|
|
|
if (navMeshPath.status != NavMeshPathStatus.PathComplete)
|
|
|
|
{
|
|
|
|
return false;
|
2024-03-17 00:00:54 +03:00
|
|
|
}
|
|
|
|
return true;
|
2024-02-19 21:00:36 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
[ClientRpc]
|
|
|
|
void RpcKillPlayer(Transform target)
|
|
|
|
{
|
|
|
|
Interactions interactions = target.GetComponent<Interactions>();
|
|
|
|
|
|
|
|
if (interactions != null) interactions.DropProp();
|
|
|
|
|
|
|
|
target.GetComponent<Pawn>().Die();
|
|
|
|
}
|
|
|
|
|
|
|
|
IEnumerator AfterKillTimer()
|
|
|
|
{
|
2024-03-17 00:00:54 +03:00
|
|
|
isKilling = true;
|
2024-02-19 21:00:36 +03:00
|
|
|
_target = null;
|
2024-03-17 01:02:25 +03:00
|
|
|
_speedMul = 0;
|
2024-03-17 00:00:54 +03:00
|
|
|
yield return new WaitForSeconds(7);
|
2024-03-17 01:02:25 +03:00
|
|
|
_speedMul = 1;
|
2024-03-17 00:00:54 +03:00
|
|
|
isKilling = false;
|
2024-02-19 21:00:36 +03:00
|
|
|
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()
|
|
|
|
{
|
|
|
|
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)
|
|
|
|
{
|
2024-03-17 01:26:13 +03:00
|
|
|
print(this.name + " taken damage epta");
|
2024-03-17 00:00:54 +03:00
|
|
|
canAttack = false;
|
2024-03-17 01:02:25 +03:00
|
|
|
_speedMul = 0;
|
2024-02-19 21:00:36 +03:00
|
|
|
animator.SetTrigger("damage");
|
|
|
|
hitVFX.Stop();
|
|
|
|
hitVFX.Play();
|
2024-03-17 00:00:54 +03:00
|
|
|
StartCoroutine(AfterTakeDamage());
|
|
|
|
}
|
|
|
|
|
|
|
|
IEnumerator AfterTakeDamage()
|
|
|
|
{
|
2024-03-17 01:02:25 +03:00
|
|
|
yield return new WaitForSeconds(6);
|
|
|
|
_speedMul = 1;
|
2024-03-17 00:00:54 +03:00
|
|
|
canAttack = true;
|
2024-02-19 21:00:36 +03:00
|
|
|
}
|
2024-03-17 00:00:54 +03:00
|
|
|
}
|