step-timeline/Scripts/StepSwitches/WatchAndAssistStepSwitch.cs

195 lines
6.2 KiB
C#

using UnityEngine;
using TriInspector;
namespace R0bbie.Timeline
{
/// <summary>
/// Watch for an event to happen, and if it doesn't after some delay, trigger a step to assist the player
/// </summary>
[AddComponentMenu("Timeline/StepSwitches/Watch and Assist (Step Switch)")]
public class WatchAndAssistStepSwitch : StepSwitch
{
public enum WatchForEvent
{
OnCommandComplete,
OnExternalTrigger
}
[Title("Switch Setup")]
[SerializeField] WatchForEvent watchForEvent;
[ShowIf("watchForEvent", WatchForEvent.OnCommandComplete)]
[SerializeField] StepCmd watchOnCommandComplete;
[ShowIf("watchForEvent", WatchForEvent.OnExternalTrigger)]
[SerializeField] TimelineTrigger watchTrigger;
[SerializeField, Tooltip("If watching for OnCommandComplete will skip if command previously completed, if OnExternalTrigger then if prev triggered")] bool skipIfPreviouslyTriggered;
[SerializeField] float waitForSeconds;
[Title("Switch Options")]
[SerializeField, Tooltip("Step switched to if event isn't detected before waitForSeconds runs out")]
Step assistAfterDelayStep;
[SerializeField, Tooltip("Step switched to if event is detected before waitForSeconds is up. If left null will just continue to next step in timeline")]
Step watchedEventPerformedStep;
float timer;
bool timedOut;
/// <summary>
/// Initialise the StepSwitch with Timeline
/// </summary>
public override void Init(StepTimeline _stepTimeline)
{
// Setup necessary refs such as parent timeline
attachedStepTimeline = _stepTimeline;
// Inactive by default
activeMode = Mode.Inactive;
// Init all child steps
if (assistAfterDelayStep)
assistAfterDelayStep.Init(attachedStepTimeline, this);
if (watchedEventPerformedStep)
watchedEventPerformedStep.Init(attachedStepTimeline, this);
ResetTimer();
init = true;
}
/// <summary>
/// Initialise the StepSwitch with StepController
/// </summary>
public override void Init(StepController _controller)
{
// Setup necessary refs such as parent controller
attachedController = _controller;
// Inactive by default
activeMode = Mode.Inactive;
// Init all child steps
if (assistAfterDelayStep)
assistAfterDelayStep.Init(attachedController, this);
if (watchedEventPerformedStep)
watchedEventPerformedStep.Init(attachedController, this);
ResetTimer();
init = true;
}
void ResetTimer()
{
timer = 0;
timedOut = false;
}
/// <summary>
/// Play this StepSwitch
/// </summary>
public override void Play()
{
isActive = true;
Debug.Log(name + " - Started");
// Set mode to waiting for event
activeMode = Mode.WaitingForEvent;
// Continue immediately if action we're watching for was previously performed?
if (skipIfPreviouslyTriggered)
{
if (watchForEvent == WatchForEvent.OnCommandComplete && watchOnCommandComplete)
{
if (watchOnCommandComplete.completed)
{
activeStepOption = watchedEventPerformedStep;
PlaySetStepOption();
}
}
else if (watchForEvent == WatchForEvent.OnExternalTrigger && watchTrigger)
{
waitingForExternalTrigger = true;
if (watchTrigger.triggered)
{
activeStepOption = watchedEventPerformedStep;
PlaySetStepOption();
}
}
}
}
void PlaySetStepOption()
{
// Play the selected option, unless it's null (in which case just play next step in timeline)
if (activeStepOption)
{
activeMode = Mode.PlayingChildStep;
activeStepOption.Play();
}
else
{
Debug.Log("The option selected by the step switch was null, so just proceeding to next step in timeline.");
Continue();
}
}
void Update()
{
// If step switch isn't active, is paused, has already timed out, or isn't currently waiting for an event to happen (i.e. may be playing a child step already), then don't handle timer
if (!isActive || isPaused || timedOut || activeMode != Mode.WaitingForEvent)
return;
// Add to timer
timer += Time.deltaTime;
// Time out once we've reached a set target seconds
if (timer > waitForSeconds)
timedOut = true;
if (timedOut)
{
activeStepOption = assistAfterDelayStep;
PlaySetStepOption();
return;
}
// Wait for delay / action to be performed
if (watchForEvent == WatchForEvent.OnCommandComplete && watchOnCommandComplete)
{
if (watchOnCommandComplete.completed)
{
activeStepOption = watchedEventPerformedStep;
PlaySetStepOption();
}
}
else if (watchForEvent == WatchForEvent.OnExternalTrigger && watchTrigger)
{
if (watchTrigger.triggered)
{
activeStepOption = watchedEventPerformedStep;
PlaySetStepOption();
}
}
}
}
}