Encounter / Assets / Scripts / BattleLogic / CheckCameraUtil.cs
CheckCameraUtil.cs
Raw
using Cinemachine;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using TMPro;
using UnityEngine;

/// <summary>
/// Handles individual Check Utility designs for points, tracking, and speed 
/// with their necessary dialogues
/// </summary>
public class CheckCameraUtil : MonoBehaviour
{
    [Header("Points")]
    [SerializeField] private Transform TrackingPoint;   // The point that is tracked by the virtual camera as this transform moves between point one and two
    [SerializeField] private Transform PointOne;        // The beginning point for when a check is initiated
    [SerializeField] private Transform PointTwo;        // The ending point for when a check is completing

    [Header("Canvas Components")]
    [SerializeField] private GameObject hpBar;          // Reference to the health bar of the enemy
    [SerializeField] private TextMeshProUGUI enemyName; // Reference to the text of the enemy name
    [SerializeField] private TextMeshProUGUI checkText; // Reference to the text used for the check dialogue
    [SerializeField] private GameObject afflictionsBar; // Reference to the bar that handles modifiers and afflictions

    [Header("Factors")]
    [SerializeField] private float Speed;               // The speed at which the TrackingPoint follows through the two points with the camera
    [SerializeField] private float Ortho;               // The Orthographic size for the camera when looking at the enemy sprite 

    [Header("Dialogue")]
    [SerializeField] private DialogueSO dialogue;       // The collection of dialogue and voice acting for the particular check

    private bool active;                                // Trigger indicator if the update method should begin the moving process
    private bool routineCheck;                          // Check for when a dialogue is finished and the next can start
    private Task checkFulfilled;                        // The task to be fulfilled during the check process
    private Coroutine dialogueRoutine;                  // The coroutine holder for the dialogue and voice acting
    private int counter;                                // The current index of the dialogue
    private CinemachineVirtualCamera cam;               // The holder for the virtual camera

    /// <summary>
    /// Retrieves the tracking point for the starting process of the animation scene
    /// </summary>
    /// <returns>The position/transform of the tracking point</returns>
    public Transform AcquireTrackingPoint()
        => TrackingPoint;

    private void Update()
    {
        // When a dialogue part is finished the coroutine is free'd while the counter is incremented to prepare for the next dialogue
        if (routineCheck)
        {
            dialogueRoutine = null;
            counter++;
            routineCheck = false;
        }

        if (active)
        {
            if (counter < dialogue.dialogues.Count)
                dialogueRoutine ??= StartCoroutine(DialogueCapsulation());

            float distance = Vector2.Distance(TrackingPoint.position, PointTwo.position);
            
            if (distance > 0.1f)
                TrackingPoint.position = Vector2.MoveTowards(TrackingPoint.position, PointTwo.position, Speed * Time.deltaTime);
            else
                checkFulfilled = Task.CompletedTask;
        }
    }
    /// <summary>
    /// Begins the process of stating the check dialogue for the counter index
    /// </summary>
    /// <returns></returns>
    private IEnumerator DialogueCapsulation()
    {
        string text = dialogue.dialogues[counter];
        checkText.text = text;
        float timer = -1f;
        // Try catch is for when dialogue clips are not yet implemented
        // timer acts as a secondary check that the dialogue is properly moving through
        try
        {
            if (dialogue.dialogueClips[counter] == null)
                throw new NullReferenceException();

            AudioClip clip = dialogue.dialogueClips[counter];
            DialogueManager.Instance.PlayDialogueClip(clip);
        }
        catch (NullReferenceException) when (dialogue.dialogueClips[counter] == null) 
        {
            Debug.LogWarning($"Skipping audio clip in {dialogue.name} at position {counter}.");
            timer = 5f;
        }
        while (DialogueManager.Instance.CheckDialogueStatus() || timer > 0f)
        {
            timer -= Time.deltaTime;
            yield return null;
        }

        routineCheck = true;
    }
    /// <summary>
    /// Switches the enemy canvas component on and off while switching the Check Text to the opposite of what the trigger is
    /// </summary>
    /// <param name="trigger">Indicator if the canvas components should be on or off</param>
    private async Task SwitchComponents(bool trigger)
    {
        hpBar.SetActive(!trigger);
        enemyName.enabled = !trigger;
        afflictionsBar.SetActive(!trigger);

        checkText.enabled = trigger;
        cam.gameObject.SetActive(trigger);
        active = trigger;

        await Task.CompletedTask;
    }
    /// <summary>
    /// Initializes the start of a check command
    /// </summary>
    /// <param name="checkTrackCamera">The camera to manipulate its parameters</param>
    /// <returns>End of Initialization check</returns>
    public async Task StartCheckDialogue(CinemachineVirtualCamera checkTrackCamera)
        => await ProcessCheck(checkTrackCamera);
   
    private async Task ProcessCheck(CinemachineVirtualCamera checkTrackCamera)
    {
        // Calibrate and set all of the necessary parameters
        TrackingPoint.position = PointOne.position;
        counter = 0;
        checkFulfilled = null;
        cam = checkTrackCamera;
        cam.m_Lens.OrthographicSize = Ortho;
        await SwitchComponents(true);

        // Freezes this task while the task is not complete
        while (checkFulfilled is null)
            await Task.Yield();

        // Disables the virtual camera following the tracking point before switching back
        // to the main camera with its designated ortho size
        await SwitchComponents(false);
        Camera.main.orthographicSize = Globals.MainCameraOrtho;
        Camera.main.transform.position = Globals.MainCameraPosition;
        await Task.CompletedTask;
    }
}