RiftMayhem/Assets/Scripts/NPC/BossController.cs
Pedro Gomes b16bbc3c73 Update Targeting system
- Targetting tags can now hold more than one tag, keeping IsValidTarget, AlliesContains and HasSameTag checks available.
- Added generic target tags for enemies and players
- Optional specific targetting tags if needed for future enhanced targetting
2024-07-25 22:04:25 +01:00

270 lines
7.5 KiB
C#

using Photon.Pun;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BossController : NPCController
{
[Header("Boss Related:")]
[SerializeField] protected GameEvent onBossDead;
[SerializeField] protected float bossRangedAttacksRange;
[SerializeField] protected float bossMeleeAttacksRange;
protected BossAbilityBinder bossAbilityBinder;
protected bool lockedInPhase = false;
protected float targetDistance = float.MaxValue;
protected float distance;
protected Taggable resultTarget;
protected float endSearchTime;
protected Collider[] hits;
protected override void Awake()
{
base.Awake();
bossAbilityBinder = GetComponent<BossAbilityBinder>();
}
[PunRPC]
protected override void RPC_OnDeath(bool lootDropped)
{
if (isDead) return;
onBossDead.Raise();
base.RPC_OnDeath(lootDropped);
}
protected override void Start()
{
base.Start();
if (!photonView.IsMine) return;
CheckSurroundings();
LockInTarget(CheckClosestTarget());
}
protected override void Update()
{
if (!photonView.IsMine) return;
if (isDead) return;
if (PrimaryMovementBehaviourCheck())
{
PerformPrimaryMovementBehaviour();
}
else if (agent.remainingDistance <= agent.stoppingDistance)
agent.isStopped = true;
counter += Time.deltaTime;
if (counter >= timeBetweenAttacks)
{
if (HighestPriorityCheck())
{
PerformHighestPriorityAction();
}
else if (SecondHighestPriorityCheck())
{
PerformSecondHighestPriorityAction();
}
else if (ThirdHighestPriorityCheck())
{
PerformThirdHighestPriorityAction();
}
else
{
agent.isStopped = false;
}
}
else
{
agent.isStopped = false;
}
}
protected virtual bool PrimaryMovementBehaviourCheck()
{
return Vector3.Distance(agent.transform.position, currentTarget.transform.position) > (bossRangedAttacksRange * 0.8f);
}
protected virtual bool HighestPriorityCheck()
{
return bossAbilityBinder.CanCastUltimate();
}
protected virtual bool SecondHighestPriorityCheck()
{
return (bossAbilityBinder.CanCastCoreAbility() && agent.remainingDistance <= bossRangedAttacksRange);
}
protected virtual bool ThirdHighestPriorityCheck()
{
return agent.remainingDistance <= bossMeleeAttacksRange;
}
protected virtual void PerformPrimaryMovementBehaviour()
{
patrolDestination = currentTarget.transform.position;
patrolDestination.y = 0f;
agent.SetDestination(patrolDestination);
agent.isStopped = false;
}
protected virtual void PerformHighestPriorityAction()
{
PerformUltimate();
}
protected virtual void PerformSecondHighestPriorityAction()
{
PerformCoreAbility();
}
protected virtual void PerformThirdHighestPriorityAction()
{
PerformMeleeAbility();
}
protected virtual void PerformUltimate()
{
Debug.Log("INSIDE CAN CAST ULTIMATE: " + bossAbilityBinder.CanCastUltimate());
ResetValuesOnAbilityPerformed();
bossAbilityBinder.UseUltimateAbility(currentTarget.transform);
}
protected virtual void PerformCoreAbility()
{
ResetValuesOnAbilityPerformed();
bossAbilityBinder.UseCoreAbility(currentTarget.transform.position);
}
protected virtual void PerformMeleeAbility()
{
ResetValuesOnAbilityPerformed();
bossAbilityBinder.UseMeleeAbility();
}
protected virtual void ResetValuesOnAbilityPerformed()
{
agent.isStopped = true;
counter = 0f;
}
protected virtual Taggable CheckClosestTarget()
{
targetDistance = float.MaxValue;
Debug.Log("CLOSEST COUNT: " + possibleTargets.Count);
for (int i = 0; i < possibleTargets.Count; i++)
{
distance = Vector3.Distance(possibleTargets[i].transform.position, agent.transform.position);
if (distance < targetDistance)
{
targetDistance = distance;
resultTarget = possibleTargets[i];
}
}
return resultTarget;
}
protected virtual Taggable CheckFurthestAwayTarget()
{
targetDistance = 0f;
for (int i = 0; i < possibleTargets.Count; i++)
{
distance = Vector3.Distance(possibleTargets[i].transform.position, agent.transform.position);
if (distance > targetDistance)
{
targetDistance = distance;
resultTarget = possibleTargets[i];
}
}
return resultTarget;
}
protected virtual IEnumerator TargetLockedInPhaseDurationCoroutine()
{
yield return new WaitForSeconds(GameConstants.GameBalancing.BossTargetLockInPhaseDuration);
SearchForNewTargetToLockIn();
}
protected virtual IEnumerator SearchForNewTargetToLockInCoroutine()
{
endSearchTime = Time.time + GameConstants.GameBalancing.BossSearchForNewTargetLockInDuration;
while (Time.time < endSearchTime)
{
UpdateCurrentTarget(possibleTargets[Random.Range(0, possibleTargets.Count)]);
yield return new WaitForSeconds(GameConstants.GameBalancing.BossSearchForNewTargetLockInDuration / 3);
}
LockInTarget(CheckClosestTarget());
}
protected virtual void LockInTarget(Taggable target)
{
lockedInPhase = true;
UpdateCurrentTarget(target);
Debug.Log("Target Locked In: " + target.name);
StartCoroutine(TargetLockedInPhaseDurationCoroutine());
}
protected virtual void SearchForNewTargetToLockIn()
{
lockedInPhase = false;
Debug.Log("Searching for new lockin: ");
StartCoroutine(SearchForNewTargetToLockInCoroutine());
}
protected virtual void UpdateCurrentTarget(Taggable target)
{
currentTarget = target;
SetupAgentStats();
}
protected virtual void SetupAgentStats()
{
agent.speed = chasingAgentSpeed;
patrolDestination = currentTarget.transform.position;
patrolDestination.y = 0f;
agent.SetDestination(patrolDestination);
}
protected virtual void CheckSurroundings()
{
if (!photonView.IsMine) return;
hits = Physics.OverlapSphere(this.transform.position, sightRange);
Debug.Log("CHECK SURROUNDINGS COUNT: " + hits.Length);
foreach (Collider collider in hits)
{
Debug.Log("CHECKING COLLIDER: " + collider.name);
otherView = collider.GetComponentInParent<PhotonView>();
if (otherView != null)
{
if (otherView == photonView) continue;
}
possibleTarget = collider.GetComponentInParent<Taggable>();
if (possibleTarget == null) continue;
//if (possibleTarget.targetTag == myTag.targetTag || myTag.targetTag.AlliedTags.Contains(possibleTarget.targetTag)) continue;
if (possibleTarget.HasSameTag(myTag.targetTag) || myTag.AlliedTagsContains(possibleTarget.targetTag)) continue;
if (possibleTargets.Contains(possibleTarget)) continue;
Debug.Log("ADDING TARGET " + possibleTarget.name);
possibleTargets.Add(possibleTarget);
}
}
}