diff --git a/Assets/Resources/Sprites/Games/MannequinFactory/Animations/EyeStamps/EyeStampAnim.controller b/Assets/Resources/Sprites/Games/MannequinFactory/Animations/EyeStamps/EyeStampAnim.controller index 7ae2753ea..79a740b6c 100644 --- a/Assets/Resources/Sprites/Games/MannequinFactory/Animations/EyeStamps/EyeStampAnim.controller +++ b/Assets/Resources/Sprites/Games/MannequinFactory/Animations/EyeStamps/EyeStampAnim.controller @@ -125,6 +125,6 @@ AnimatorStateMachine: m_StateMachineBehaviours: [] m_AnyStatePosition: {x: 50, y: 10, z: 0} m_EntryPosition: {x: 50, y: 120, z: 0} - m_ExitPosition: {x: 800, y: 120, z: 0} + m_ExitPosition: {x: 50, y: 300, z: 0} m_ParentStateMachinePosition: {x: 800, y: 20, z: 0} m_DefaultState: {fileID: 903278139598467881} diff --git a/Assets/Resources/Sprites/Games/MannequinFactory/Animations/Hand/HandAnim.controller b/Assets/Resources/Sprites/Games/MannequinFactory/Animations/Hand/HandAnim.controller index 6c6c518f0..7f27fe35b 100644 --- a/Assets/Resources/Sprites/Games/MannequinFactory/Animations/Hand/HandAnim.controller +++ b/Assets/Resources/Sprites/Games/MannequinFactory/Animations/Hand/HandAnim.controller @@ -51,7 +51,7 @@ AnimatorStateMachine: m_StateMachineBehaviours: [] m_AnyStatePosition: {x: 50, y: 10, z: 0} m_EntryPosition: {x: 50, y: 120, z: 0} - m_ExitPosition: {x: 800, y: 120, z: 0} + m_ExitPosition: {x: 50, y: 300, z: 0} m_ParentStateMachinePosition: {x: 800, y: 20, z: 0} m_DefaultState: {fileID: -7836894309669860130} --- !u!91 &9100000 diff --git a/Assets/Scripts/Games/MannequinFactory/MannequinFactory.cs b/Assets/Scripts/Games/MannequinFactory/MannequinFactory.cs index 24e51a7b1..fa5860fe3 100644 --- a/Assets/Scripts/Games/MannequinFactory/MannequinFactory.cs +++ b/Assets/Scripts/Games/MannequinFactory/MannequinFactory.cs @@ -15,39 +15,49 @@ namespace HeavenStudio.Games.Loaders { new GameAction("headOut", "Send Head Out") { + inactiveFunction = delegate { + MannequinFactory.HeadOutSFX(eventCaller.currentEntity.beat, 0); + }, function = delegate { + MannequinFactory.HeadOutSFX(eventCaller.currentEntity.beat, 0); if (eventCaller.gameManager.minigameObj.TryGetComponent(out MannequinFactory instance)) { - var e = eventCaller.currentEntity; - instance.HeadOut(e.beat, 1); + instance.HeadOut(eventCaller.currentEntity.beat, 0); } - }, + }, defaultLength = 7, }, new GameAction("misalignedHeadOut", "Send Misaligned Head Out") { + inactiveFunction = delegate { + MannequinFactory.HeadOutSFX(eventCaller.currentEntity.beat, 1); + }, function = delegate { + MannequinFactory.HeadOutSFX(eventCaller.currentEntity.beat, 1); if (eventCaller.gameManager.minigameObj.TryGetComponent(out MannequinFactory instance)) { - var e = eventCaller.currentEntity; - instance.HeadOut(e.beat, 2); + instance.HeadOut(eventCaller.currentEntity.beat, 1); } - }, + }, defaultLength = 7, }, new GameAction("randomHeadOut", "Send Random Head Out") { + // inactiveFunction = delegate { + // int random = Random.Range(0, 2); + // MannequinFactory.HeadOutSFX(eventCaller.currentEntity.beat, random); + // }, function = delegate { + int random = Random.Range(0, 2); + MannequinFactory.HeadOutSFX(eventCaller.currentEntity.beat, random); if (eventCaller.gameManager.minigameObj.TryGetComponent(out MannequinFactory instance)) { - var e = eventCaller.currentEntity; - instance.HeadOut(e.beat, 0); + instance.HeadOut(eventCaller.currentEntity.beat, random); } - }, + }, defaultLength = 7, }, new GameAction("changeText", "Change Text") { function = delegate { if (eventCaller.gameManager.minigameObj.TryGetComponent(out MannequinFactory instance)) { - var e = eventCaller.currentEntity; instance.SignText.text = eventCaller.currentEntity["text"]; } }, @@ -75,11 +85,10 @@ namespace HeavenStudio.Games.Loaders }, resizable = true }, - } - // , - // new List() {"agb", "normal"}, - // "agbmannequin", "en", - // new List() {} + }, + new List() {"agb", "normal"}, + "agbmannequin", "en", + new List() {} ); } } @@ -99,20 +108,17 @@ namespace HeavenStudio.Games public TMP_Text SignText; public GameObject MannequinHeadObject; + public double slapScheduledBeat = double.MinValue; + + private double colorStartBeat = -1; + private float colorLength = 0f; + private Color colorStart, colorEnd = new Color(0.97f, 0.94f, 0.51f, 1f); // default bg color + private Util.EasingFunction.Ease colorEase; + protected static bool IA_PadLeft(out double dt) { return PlayerInput.GetPadDown(InputController.ActionsPad.Left, out dt); } - protected static new bool IA_TouchFlick(out double dt) - { - return PlayerInput.GetTouchUp(InputController.ActionsTouch.Tap, out dt) && PlayerInput.GetFlick(out _) - && !instance.IsExpectingInputNow(InputAction_Second); - } - protected static bool IA_TouchPress(out double dt) - { - return PlayerInput.GetTouchDown(InputController.ActionsTouch.Tap, out dt)// && !PlayerInput.GetFlick(out _) - && !instance.IsExpectingInputNow(InputAction_First); - } public static PlayerInput.InputAction InputAction_First = new("AgbMannequinFactoryTouchFirst", new int[] { IAPressCat, IAPressCat, IAPressCat }, @@ -120,39 +126,55 @@ namespace HeavenStudio.Games public static PlayerInput.InputAction InputAction_Second = new("AgbMannequinFactoryTouchSecond", new int[] { IAPressCat, IAPressCat, IAPressCat }, - IA_PadBasicPress, IA_TouchPress, IA_Empty); - - // awww man a static instance 😢 - private static MannequinFactory instance; - - private void Awake() - { - instance = this; - } + IA_PadBasicPress, IA_TouchBasicPress, IA_Empty); private void Update() { - bool touch = PlayerInput.CurrentControlStyle == InputController.ControlStyles.Touch; - if (PlayerInput.GetIsAction(InputAction_First) && (!IsExpectingInputNow(InputAction_First) || (touch && !IsExpectingInputNow(InputAction_First) && !IsExpectingInputNow(InputAction_Second)))) + if (PlayerInput.GetIsAction(InputAction_First) && !IsExpectingInputNow(InputAction_First) + && !HandAnim.IsPlayingAnimationNames("SlapEmpty", "SlapJust")) { HandAnim.DoScaledAnimationAsync("SlapEmpty", 0.3f); } - if (PlayerInput.GetIsAction(InputAction_Second) && (!IsExpectingInputNow(InputAction_Second) || (touch && !IsExpectingInputNow(InputAction_First) && !IsExpectingInputNow(InputAction_Second)))) + bool canSlap = PlayerInput.CurrentControlStyle != InputController.ControlStyles.Touch || slapScheduledBeat < conductor.songPositionInBeatsAsDouble; + + if (PlayerInput.GetIsAction(InputAction_Second) && !IsExpectingInputNow(InputAction_Second) + && !StampAnim.IsPlayingAnimationNames("StampEmpty", "StampJust") && canSlap) { StampAnim.DoScaledAnimationAsync("StampEmpty", 0.3f); } - BackgroundColorUpdate(); + float normalizedBeat = Mathf.Clamp01(Conductor.instance.GetPositionFromBeat(colorStartBeat, colorLength)); + + var func = Util.EasingFunction.GetEasingFunction(colorEase); + + float newR = func(colorStart.r, colorEnd.r, normalizedBeat); + float newG = func(colorStart.g, colorEnd.g, normalizedBeat); + float newB = func(colorStart.b, colorEnd.b, normalizedBeat); + + bg.color = new Color(newR, newG, newB); } - public override void OnGameSwitch(double beat) + public override void OnPlay(double beat) => StartGame(beat, true); + public override void OnGameSwitch(double beat) => StartGame(beat, false); + + private void StartGame(double beat, bool isPlay) { var events = gameManager.Beatmap.Entities.FindAll(e => e.datamodel.Split('/')[0] == "mannequinFactory"); - foreach (var item in events.FindAll(e => e.datamodel is "headOut" or "misalignedHeadOut" or "randomHeadOut")) + foreach (var e in events) { - + if (e.beat < beat && e.beat + 2.75 > beat && e.datamodel is "mannequinFactory/headOut" or "mannequinFactory/misalignedHeadOut" /* or "mannequinFactory/randomHeadOut" */) { + int cueType = e.datamodel switch { + "mannequinFactory/headOut" => 0, + "mannequinFactory/misalignedHeadOut" => 1, + "mannequinFactory/randomHeadOut" or _ => Random.Range(0, 2), + }; + HeadOut(e.beat, cueType); + if (isPlay) { + HeadOutSFX(e.beat, cueType, beat); + } + } } var bg = events.FindLast(e => e.datamodel == "mannequinFactory/bgColor" && e.beat < beat); @@ -164,16 +186,16 @@ namespace HeavenStudio.Games } } - public static void HeadOutSFX(double beat, int cueType) + public static void HeadOutSFX(double beat, int cueType, double fromBeat = 0) { - if (cueType == 0) cueType = Random.Range(1, 3); var sfx = new List() { - new MultiSound.Sound("mannequinFactory/drum", beat ), - new MultiSound.Sound("mannequinFactory/drum", beat + 0.5), - new MultiSound.Sound("mannequinFactory/drum", beat + 1.5), - new MultiSound.Sound("mannequinFactory/drum", beat + 2 ), + new("mannequinFactory/drum", beat ), + new("mannequinFactory/drum", beat + 0.5), + new("mannequinFactory/drum", beat + 1.5), + new("mannequinFactory/drum", beat + 2 ), + new("mannequinFactory/whoosh", beat + 5), }; - if (cueType == 1) { + if (cueType == 0) { for (int i = 0; i < 7; i++) { sfx.Add(new($"mannequinFactory/drumroll{i + 1}", beat + 3 + (i * 0.1667))); } @@ -181,9 +203,14 @@ namespace HeavenStudio.Games sfx.AddRange(new MultiSound.Sound[] { new("mannequinFactory/drum", beat + 0.75), new("mannequinFactory/drum", beat + 1 ), + new("mannequinFactory/whoosh", beat + 3), }); } - MultiSound.Play(sfx.ToArray(), forcePlay: true); + sfx.Sort((x, y) => x.beat.CompareTo(y.beat)); + sfx.RemoveAll(x => x.beat < fromBeat); + if (sfx.Count > 0) { + MultiSound.Play(sfx.ToArray(), forcePlay: true); + } } public void HeadOut(double beat, int cueType) @@ -191,26 +218,7 @@ namespace HeavenStudio.Games MannequinHead head = Instantiate(MannequinHeadObject, transform).GetComponent(); head.game = this; head.startBeat = beat; - head.needClap = cueType == 2; - } - - private double colorStartBeat = -1; - private float colorLength = 0f; - private Color colorStart, colorEnd = new Color(0.97f, 0.94f, 0.51f, 1f); // obviously put to the default colour of the game - private Util.EasingFunction.Ease colorEase; // putting Util in case this game is using Jukebox - - //call this in update - private void BackgroundColorUpdate() - { - float normalizedBeat = Mathf.Clamp01(Conductor.instance.GetPositionFromBeat(colorStartBeat, colorLength)); - - var func = Util.EasingFunction.GetEasingFunction(colorEase); - - float newR = func(colorStart.r, colorEnd.r, normalizedBeat); - float newG = func(colorStart.g, colorEnd.g, normalizedBeat); - float newB = func(colorStart.b, colorEnd.b, normalizedBeat); - - bg.color = new Color(newR, newG, newB); + head.needSlap = cueType == 1; } public void BackgroundColor(double beat, float length, Color colorStartSet, Color colorEndSet, int ease) diff --git a/Assets/Scripts/Games/MannequinFactory/MannequinHead.cs b/Assets/Scripts/Games/MannequinFactory/MannequinHead.cs index 0eda01fd5..98a9dd98c 100644 --- a/Assets/Scripts/Games/MannequinFactory/MannequinHead.cs +++ b/Assets/Scripts/Games/MannequinFactory/MannequinHead.cs @@ -8,7 +8,7 @@ namespace HeavenStudio.Games.Scripts_MannequinFactory public class MannequinHead : MonoBehaviour { public double startBeat; - public bool needClap; + public bool needSlap; [Header("Animators")] [SerializeField] SpriteRenderer headSr; @@ -20,64 +20,67 @@ namespace HeavenStudio.Games.Scripts_MannequinFactory int turnStatus; public MannequinFactory game; - - private void Awake() - { - - } private void Start() { - turnStatus = needClap ? 0 : 1; + game.slapScheduledBeat = startBeat + 4; + + turnStatus = needSlap ? 0 : 1; headSr.sprite = heads[turnStatus]; BeatAction.New(game, new List { - new BeatAction.Action(startBeat + 1, delegate { headAnim.DoScaledAnimationAsync("Move1", 0.3f); }), - new BeatAction.Action(startBeat + 3, delegate { headAnim.DoScaledAnimationAsync("Move2", 0.3f); }), - new BeatAction.Action(startBeat + 4, delegate { + new(startBeat + 1, delegate { headAnim.DoScaledAnimationAsync("Move1", 0.3f); }), + new(startBeat + 3, delegate { if (game.gameManager.autoplay) headAnim.DoScaledAnimationAsync("Move2", 0.3f); }), + new(startBeat + 4, delegate { + PlayerActionEvent input; if (turnStatus == 1) { - game.ScheduleInput(startBeat, 5, MannequinFactory.InputAction_Second, StampJust, StampMiss, Nothing); + input = game.ScheduleInput(startBeat, 5, MannequinFactory.InputAction_Second, StampJust, StampMiss, null); } else { - game.ScheduleUserInput(startBeat, 5, MannequinFactory.InputAction_Second, StampUnJust, StampMiss, Nothing); + input = game.ScheduleUserInput(startBeat, 5, MannequinFactory.InputAction_Second, StampUnJust, StampMiss, null); } + input.IsHittable = () => !game.StampAnim.IsPlayingAnimationNames("StampEmpty", "StampJust"); }), }); - if (needClap) { - game.ScheduleInput(startBeat, 3, MannequinFactory.InputAction_First, ClapJust, ClapMiss, Nothing); - SoundByte.PlayOneShotGame("mannequinFactory/whoosh", beat: startBeat + 3); + PlayerActionEvent input; + if (needSlap) { + input = game.ScheduleInput(startBeat, 3, MannequinFactory.InputAction_First, SlapJust, SlapMiss, null); } else { - game.ScheduleUserInput(startBeat, 3, MannequinFactory.InputAction_First, ClapUnJust, ClapMiss, Nothing); - SoundByte.PlayOneShotGame("mannequinFactory/whoosh", beat: startBeat + 5); - } + input = game.ScheduleUserInput(startBeat, 3, MannequinFactory.InputAction_First, SlapUnJust, SlapMiss, null); + } + input.IsHittable = () => !game.HandAnim.IsPlayingAnimationNames("SlapEmpty", "SlapJust"); } - void ClapJust(PlayerActionEvent caller, float state) + private void SlapJust(PlayerActionEvent caller, float state) { - ClapHit(state); + SlapHit(state); headSr.sprite = heads[turnStatus]; } - void ClapUnJust(PlayerActionEvent caller, float state) + private void SlapUnJust(PlayerActionEvent caller, float state) { eyesSr.transform.localScale = new Vector2(-1, 1); headSr.transform.localScale = new Vector2(-1, 1); headSr.sprite = heads[0]; game.ScoreMiss(); - ClapHit(state); + SlapHit(state); } - void ClapHit(float state) + private void SlapHit(float state) { + if (state >= 1f || state <= -1f) SoundByte.PlayOneShot("nearMiss"); turnStatus++; SoundByte.PlayOneShotGame("mannequinFactory/slap"); game.HandAnim.DoScaledAnimationAsync("SlapJust", 0.3f); headAnim.Play("Slapped", 0, 0); } - void ClapMiss(PlayerActionEvent caller) { } + private void SlapMiss(PlayerActionEvent caller) + { + headAnim.DoScaledAnimationAsync("Move2", 0.3f); + } - void StampHit(float state) + private void StampHit(float state) { if (state >= 1f || state <= -1f) SoundByte.PlayOneShot("nearMiss"); headAnim.DoScaledAnimationAsync("Stamp", 0.3f); @@ -86,7 +89,7 @@ namespace HeavenStudio.Games.Scripts_MannequinFactory eyesSr.gameObject.SetActive(true); } - void StampJust(PlayerActionEvent caller, float state) + private void StampJust(PlayerActionEvent caller, float state) { StampHit(state); @@ -100,7 +103,7 @@ namespace HeavenStudio.Games.Scripts_MannequinFactory }); } - void StampUnJust(PlayerActionEvent caller, float state) + private void StampUnJust(PlayerActionEvent caller, float state) { StampHit(state); eyesSr.sprite = eyes[1]; @@ -113,7 +116,7 @@ namespace HeavenStudio.Games.Scripts_MannequinFactory }); } - void StampMiss(PlayerActionEvent caller) + private void StampMiss(PlayerActionEvent caller) { headAnim.DoScaledAnimationAsync("Move3", 0.3f); BeatAction.New(game, new List { @@ -124,8 +127,6 @@ namespace HeavenStudio.Games.Scripts_MannequinFactory }); } - void Nothing(PlayerActionEvent caller) { } - // animation event public void DestroySelf() { diff --git a/Assets/Scripts/Util/AnimationHelpers.cs b/Assets/Scripts/Util/AnimationHelpers.cs index 3a5b592aa..52610a4a7 100644 --- a/Assets/Scripts/Util/AnimationHelpers.cs +++ b/Assets/Scripts/Util/AnimationHelpers.cs @@ -73,6 +73,10 @@ namespace HeavenStudio.Util if (!double.IsNaN(startBeat)) { var cond = Conductor.instance; var animClip = Array.Find(anim.runtimeAnimatorController.animationClips, x => x.name == animName); + if (animClip == null) { + Debug.LogError("Animation clip " + animName + " not found!"); + return; + } double animLength = cond.SecsToBeats(animClip.length, cond.GetBpmAtBeat(startBeat)); pos = cond.GetPositionFromBeat(startBeat, animLength) * timeScale; } else {