RiftMayhem/Assets/Scripts/NPC/NPCController.cs
Pedro Gomes 7d28666e14 Boss & job complete Update
- Boss after rift clearance
- job completed event
- job rewards awarded on completion
2024-06-12 23:12:39 +01:00

257 lines
7.0 KiB
C#

using Photon.Pun;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class NPCController : MonoBehaviour
{
[Header("Events:")]
[SerializeField] private GameEvent_Float experienceOnDeath;
[Header("Boss-Related:")]
[SerializeField] private bool isBoss;
[SerializeField] private GameEvent onBossDead;
[Header("Settings:")]
[SerializeField] private float sightRange;
[SerializeField] private float sightRangeMultiplierForProjectiles;
[SerializeField] private float distanceToChangePatrolDestination;
[SerializeField] private float patrolAgentSpeed;
[SerializeField] private float chasingAgentSpeed;
[SerializeField] private float timeBetweenAttacks = 1f;
[HideInInspector]
public PhotonView photonView;
[HideInInspector]
public Taggable myTag;
NavMeshAgent agent;
public List<Taggable> possibleTargets = new List<Taggable>();
public Taggable currentTarget;
SphereCollider sight;
PhotonView otherView;
Taggable possibleTarget;
NPCAbilityBinder abilityBinder;
DropTable dropTable;
Vector3 patrolDestination = new Vector3();
private float counter = 0f;
Health health;
bool isDead = false;
#region Death Animation
float moveSpeed = 0.5f; // Speed of the downwards movement
float moveDistance = 3.0f; // Distance to move downwards
float moveDelay = 0.25f; // Delay before starting the movement
private Vector3 startPosition;
private Vector3 endPosition;
#endregion
private void Awake()
{
myTag = GetComponentInParent<Taggable>();
agent = GetComponentInParent<NavMeshAgent>();
photonView = GetComponentInParent<PhotonView>();
abilityBinder = GetComponent<NPCAbilityBinder>();
health = GetComponent<Health>();
dropTable = GetComponentInChildren<DropTable>();
if (!photonView.IsMine) return;
}
// Start is called before the first frame update
void Start()
{
if (!photonView.IsMine) return;
sight = this.gameObject.AddComponent<SphereCollider>();
sight.radius = sightRange;
sight.isTrigger = true;
isDead = false;
counter = timeBetweenAttacks / 2f;
health.onDeath.AddListener(OnDeath);
}
private void OnDeath()
{
photonView.RPC(nameof(RPC_OnDeath), RpcTarget.All, dropTable.CalculateLootDrop());
}
[PunRPC]
private void RPC_OnDeath(bool lootDropped)
{
if (isDead) return;
Debug.Log($"{this.gameObject.name} died!");
isDead = true;
agent.enabled = false;
experienceOnDeath.Raise(health.GetMaxValue() * 3f);
dropTable.DropLoot(lootDropped);
if (isBoss)
onBossDead.Raise();
if (!photonView.IsMine) return;
StartCoroutine(AnimateOnDeath());
}
IEnumerator AnimateOnDeath()
{
startPosition = transform.position;
endPosition = transform.position - Vector3.up * moveDistance;
yield return new WaitForSeconds(moveDelay);
float elapsedTime = 0.0f;
while (elapsedTime < 1.0f)
{
// Increment elapsed time based on Time.deltaTime
elapsedTime += Time.deltaTime * moveSpeed;
// Move the transform towards the end position
transform.position = Vector3.Lerp(transform.position, endPosition, elapsedTime);
yield return null; // Yielding null will make the coroutine wait until the next frame
}
DestroyAfterEffect();
}
private void DestroyAfterEffect()
{
if (!photonView.IsMine) return;
PhotonNetwork.Destroy(this.gameObject);
}
private void Update()
{
if (!photonView.IsMine) return;
if (isDead) return;
if (possibleTargets.Count <= 0)
{
if (currentTarget != null)
{
currentTarget = null;
PatrolNewPosition();
}
if (agent.destination == null)
{
PatrolNewPosition();
}
else if (agent.remainingDistance < distanceToChangePatrolDestination)
{
PatrolNewPosition();
}
}
else
{
if (possibleTargets[0] == null)
{
possibleTargets.RemoveAt(0);
return;
}
currentTarget = possibleTargets[0];
agent.speed = chasingAgentSpeed;
patrolDestination = currentTarget.transform.position;
patrolDestination.y = 0f;
agent.SetDestination(patrolDestination);
counter += Time.deltaTime;
if (agent.remainingDistance <= sightRange * sightRangeMultiplierForProjectiles)
{
agent.isStopped = true;
if (counter >= timeBetweenAttacks)
{
counter = 0f;
if (!abilityBinder.ValidCoreAbility())
abilityBinder.UsePrimaryAbility();
else
{
if (Random.Range(0, 10) > 3)
abilityBinder.UsePrimaryAbility();
else
abilityBinder.UseCoreAbility(currentTarget.transform.position);
}
}
}
else
{
agent.isStopped = false;
}
}
}
private void PatrolNewPosition()
{
agent.speed = patrolAgentSpeed;
patrolDestination.x = Random.Range(-5, 5);
patrolDestination.y = 0f;
patrolDestination.z = Random.Range(-5, 5);
agent.SetDestination(this.transform.position + patrolDestination);
agent.isStopped = false;
}
private void OnTriggerEnter(Collider other)
{
if (!photonView.IsMine) return;
otherView = other.GetComponentInParent<PhotonView>();
if (otherView != null)
{
if (otherView == photonView) return;
}
possibleTarget = other.GetComponentInParent<Taggable>();
if (possibleTarget == null) return;
if (possibleTarget.targetTag == myTag.targetTag || myTag.targetTag.AlliedTags.Contains(possibleTarget.targetTag)) return;
if (possibleTargets.Contains(possibleTarget)) return;
possibleTargets.Add(possibleTarget);
}
private void OnTriggerExit(Collider other)
{
if (!photonView.IsMine) return;
otherView = other.GetComponentInParent<PhotonView>();
if (otherView != null)
{
if (otherView == photonView) return;
}
possibleTarget = other.GetComponentInParent<Taggable>();
if (possibleTarget == null) return;
if (possibleTarget.targetTag == myTag.targetTag) return;
if (!possibleTargets.Contains(possibleTarget)) return;
possibleTargets.Remove(possibleTarget);
}
private void OnDrawGizmosSelected()
{
Gizmos.DrawWireSphere(this.transform.position, sightRange);
}
}