2022-05-03 20:36:55 +00:00
using System.Collections ;
using System.Collections.Generic ;
using UnityEngine ;
using DG.Tweening ;
using HeavenStudio.Util ;
using Starpelly ;
namespace HeavenStudio.Games
{
public class PlayerActionEvent : PlayerActionObject
{
public delegate void ActionEventCallback ( ) ;
2022-05-04 17:21:11 +00:00
public delegate void ActionEventCallbackState ( float state ) ;
2022-05-03 20:36:55 +00:00
2022-05-04 18:05:51 +00:00
public delegate void ActionEventCallbackSelf ( PlayerActionEvent evt ) ;
2022-05-03 20:36:55 +00:00
public ActionEventCallbackState OnHit ; //Function to trigger when an input has been done perfectly
public ActionEventCallback OnMiss ; //Function to trigger when an input has been missed
public ActionEventCallback OnBlank ; //Function to trigger when an input has been recorded while this is pending
2022-05-04 18:05:51 +00:00
public ActionEventCallbackSelf OnDestroy ; //Function to trigger whenever this event gets destroyed. /!\ Shouldn't be used for a minigame! Use OnMiss instead /!\
2022-05-03 20:36:55 +00:00
public float startBeat ;
public float timer ;
2022-05-04 17:21:11 +00:00
public bool canHit = true ; //Indicates if you can still hit the cue or not. If set to false, it'll guarantee a miss
public bool enabled = true ; //Indicates if the PlayerActionEvent is enabled. If set to false, it'll not trigger any events and destroy itself AFTER the event
public bool autoplayOnly = false ; //Indicates if the input event only triggers when it's autoplay. If set to true, NO Miss or Blank events will be triggered when you're not autoplaying.
public bool noAutoplay = false ; //Indicates if this PlayerActionEvent is recognized by the autoplay. /!\ Overrides autoPlayOnly /!\
// I don't know why we would ever need the noAutoplay setting, but we never know!
2022-05-03 20:36:55 +00:00
public InputType inputType ;
public void setHitCallback ( ActionEventCallbackState OnHit )
{
this . OnHit = OnHit ;
}
public void setMissCallback ( ActionEventCallback OnMiss )
{
this . OnMiss = OnMiss ;
}
public void Enable ( ) { enabled = true ; }
public void Disable ( ) { enabled = false ; }
public void CanHit ( bool canHit )
{
this . canHit = canHit ;
}
public void Update ( )
{
if ( ! Conductor . instance . NotStopped ( ) ) { CleanUp ( ) ; } // If the song is stopped entirely in the editor, destroy itself as we don't want duplicates
2022-05-04 17:21:11 +00:00
if ( noAutoplay & & autoplayOnly ) autoplayOnly = false ;
if ( noAutoplay & & triggersAutoplay ) { triggersAutoplay = false ; }
2022-05-03 20:36:55 +00:00
float normalizedBeat = Conductor . instance . GetPositionFromBeat ( startBeat , timer ) ;
StateCheck ( normalizedBeat ) ;
if ( normalizedBeat > Minigame . LateTime ( ) ) Miss ( ) ;
2022-05-04 17:21:11 +00:00
if ( IsCorrectInput ( ) & & ! autoplayOnly )
2022-05-03 20:36:55 +00:00
{
if ( state . perfect )
{
2022-05-04 17:21:11 +00:00
Hit ( 0f ) ;
2022-05-03 20:36:55 +00:00
}
else if ( state . early )
{
2022-05-04 17:21:11 +00:00
Hit ( - 1f ) ;
2022-05-03 20:36:55 +00:00
}
else if ( state . late )
{
2022-05-04 17:21:11 +00:00
Hit ( 1f ) ;
2022-05-03 20:36:55 +00:00
}
else
{
Blank ( ) ;
}
}
}
public bool IsCorrectInput ( )
{
2022-05-04 16:42:06 +00:00
// This one is a mouthful but it's an evil good to detect the correct input
// Forgive me for those input type names
2022-05-03 20:36:55 +00:00
return (
2022-05-04 16:42:06 +00:00
//General inputs, both down and up
2022-05-03 20:36:55 +00:00
( PlayerInput . Pressed ( ) & & inputType = = InputType . STANDARD_DOWN ) | |
( PlayerInput . AltPressed ( ) & & inputType = = InputType . STANDARD_ALT_DOWN ) | |
( PlayerInput . GetAnyDirectionDown ( ) & & inputType = = InputType . DIRECTION_DOWN ) | |
( PlayerInput . PressedUp ( ) & & inputType = = InputType . STANDARD_UP ) | |
( PlayerInput . AltPressedUp ( ) & & inputType = = InputType . STANDARD_ALT_UP ) | |
2022-05-04 16:42:06 +00:00
( PlayerInput . GetAnyDirectionUp ( ) & & inputType = = InputType . DIRECTION_UP ) | |
//Specific directional inputs
( PlayerInput . GetSpecificDirectionDown ( PlayerInput . DOWN ) & & inputType = = InputType . DIRECTION_DOWN_DOWN ) | |
( PlayerInput . GetSpecificDirectionDown ( PlayerInput . UP ) & & inputType = = InputType . DIRECTION_UP_DOWN ) | |
( PlayerInput . GetSpecificDirectionDown ( PlayerInput . LEFT ) & & inputType = = InputType . DIRECTION_LEFT_DOWN ) | |
( PlayerInput . GetSpecificDirectionDown ( PlayerInput . RIGHT ) & & inputType = = InputType . DIRECTION_RIGHT_DOWN ) | |
( PlayerInput . GetSpecificDirectionUp ( PlayerInput . DOWN ) & & inputType = = InputType . DIRECTION_DOWN_UP ) | |
( PlayerInput . GetSpecificDirectionUp ( PlayerInput . UP ) & & inputType = = InputType . DIRECTION_UP_UP ) | |
( PlayerInput . GetSpecificDirectionUp ( PlayerInput . LEFT ) & & inputType = = InputType . DIRECTION_LEFT_UP ) | |
( PlayerInput . GetSpecificDirectionUp ( PlayerInput . RIGHT ) & & inputType = = InputType . DIRECTION_RIGHT_UP )
2022-05-03 20:36:55 +00:00
) ;
}
//For the Autoplay
public override void OnAce ( )
{
2022-05-04 17:21:11 +00:00
Hit ( 0f ) ;
2022-05-03 20:36:55 +00:00
}
2022-05-04 17:21:11 +00:00
//The state parameter is either -1 -> Early, 0 -> Perfect, 1 -> Late
public void Hit ( float state )
2022-05-03 20:36:55 +00:00
{
if ( OnHit ! = null & & enabled )
{
if ( canHit )
{
OnHit ( state ) ;
CleanUp ( ) ;
} else
{
OnBlank ( ) ;
}
}
}
public void Miss ( )
{
2022-05-04 17:21:11 +00:00
if ( OnMiss ! = null & & enabled & & ! autoplayOnly )
2022-05-03 20:36:55 +00:00
{
OnMiss ( ) ;
}
2022-05-04 17:21:11 +00:00
CleanUp ( ) ;
2022-05-03 20:36:55 +00:00
}
public void Blank ( )
{
2022-05-04 17:21:11 +00:00
if ( OnBlank ! = null & & enabled & & ! autoplayOnly )
2022-05-03 20:36:55 +00:00
{
OnBlank ( ) ;
}
}
public void CleanUp ( )
{
2022-05-04 18:05:51 +00:00
OnDestroy ( this ) ;
2022-05-03 20:36:55 +00:00
Destroy ( this . gameObject ) ;
}
}
}