using UnityEngine; using TriInspector; namespace R0bbie.Timeline { /// /// Watch for an event to happen, and if it doesn't after some delay, trigger a step to assist the player /// [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; /// /// Initialise the StepSwitch with Timeline /// 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; } /// /// Initialise the StepSwitch with StepController /// 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; } /// /// Play this StepSwitch /// 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(); } } } } }