2023-12-14 22:59:25 +00:00
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 ;
}
2024-02-28 18:16:58 +00:00
/// <summary>
/// Reset the timer
/// </summary>
2023-12-14 22:59:25 +00:00
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 ( ) ;
}
}
}
2024-02-28 18:16:58 +00:00
/ * else
{
if ( watchForEvent = = WatchForEvent . OnExternalTrigger & & watchTrigger )
{
// Listen for trigger
watchTrigger . onTrigger . AddListener ( TriggerContinue ) ;
}
} * /
2023-12-14 22:59:25 +00:00
}
2024-02-28 18:16:58 +00:00
/// <summary>
/// Play the actively set step option
/// </summary>
/// <returns></returns>
2023-12-14 22:59:25 +00:00
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 ;
2024-02-28 18:16:58 +00:00
// If we've timed out..
2023-12-14 22:59:25 +00:00
if ( timedOut )
{
2024-02-28 18:16:58 +00:00
// Play our assist step
2023-12-14 22:59:25 +00:00
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 ( ) ;
}
}
}
}
}