From 68b2999337c8361d4ded82046bedf6df23931d6e Mon Sep 17 00:00:00 2001 From: Rapandrasmus <78219215+Rapandrasmus@users.noreply.github.com> Date: Wed, 19 Jul 2023 03:09:02 +0200 Subject: [PATCH] Quiz Show and Tambourine Reworks (#505) * Tambourine fully reworked * quiz show rework part 1 * quiz show rework part 2 * oopsie doopsie * el fix numbah two --- Assets/Resources/Games/quizShow.prefab | 113 +---- Assets/Scripts/Games/QuizShow/QSTimer.cs | 30 ++ Assets/Scripts/Games/QuizShow/QSTimer.cs.meta | 11 + Assets/Scripts/Games/QuizShow/QuizShow.cs | 394 +++++++++++++----- Assets/Scripts/Games/Tambourine/Tambourine.cs | 264 +++++++----- 5 files changed, 508 insertions(+), 304 deletions(-) create mode 100644 Assets/Scripts/Games/QuizShow/QSTimer.cs create mode 100644 Assets/Scripts/Games/QuizShow/QSTimer.cs.meta diff --git a/Assets/Resources/Games/quizShow.prefab b/Assets/Resources/Games/quizShow.prefab index 544c8a1a..7cd16b3c 100644 --- a/Assets/Resources/Games/quizShow.prefab +++ b/Assets/Resources/Games/quizShow.prefab @@ -11105,7 +11105,7 @@ Transform: - {fileID: 9173994276591170219} - {fileID: 5713690912794439839} m_Father: {fileID: 2914604841386194871} - m_RootOrder: 2 + m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &1573044212073166694 GameObject: @@ -11275,90 +11275,6 @@ SpriteRenderer: m_WasSpriteAssigned: 1 m_MaskInteraction: 0 m_SpriteSortPoint: 0 ---- !u!1 &1857446645930225069 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 782001516241619819} - - component: {fileID: 8341195154447761180} - m_Layer: 0 - m_Name: QuizShowRef - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 0 ---- !u!4 &782001516241619819 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1857446645930225069} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1.4, y: 1.4, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 2914604841386194871} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!212 &8341195154447761180 -SpriteRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1857446645930225069} - m_Enabled: 1 - m_CastShadows: 0 - m_ReceiveShadows: 0 - m_DynamicOccludee: 1 - m_StaticShadowCaster: 0 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 0 - m_RayTraceProcedural: 0 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 0 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 99 - m_Sprite: {fileID: 21300000, guid: fe5389622580b704ba776a001533f3ed, type: 3} - m_Color: {r: 1, g: 1, b: 1, a: 1} - m_FlipX: 0 - m_FlipY: 0 - m_DrawMode: 0 - m_Size: {x: 12.84, y: 7.22} - m_AdaptiveModeThreshold: 0.5 - m_SpriteTileMode: 0 - m_WasSpriteAssigned: 1 - m_MaskInteraction: 0 - m_SpriteSortPoint: 0 --- !u!1 &2039454163144846836 GameObject: m_ObjectHideFlags: 0 @@ -11812,7 +11728,6 @@ Transform: m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: - - {fileID: 782001516241619819} - {fileID: 3543715666523522543} - {fileID: 8851031114052297755} - {fileID: 5068496854343157036} @@ -11846,7 +11761,7 @@ MonoBehaviour: hostHead: {fileID: 4158127813318533208} signAnim: {fileID: 2616971115842020331} timerTransform: {fileID: 2908387998248567546} - stopWatch: {fileID: 6447998919017828740} + stopWatchRef: {fileID: 624264686619249452} blackOut: {fileID: 3849979597205832390} firstDigitSr: {fileID: 4365226235382245994} secondDigitSr: {fileID: 8225777099540804890} @@ -22094,7 +22009,7 @@ Transform: - {fileID: 6747383677754197943} - {fileID: 2301657995609138378} m_Father: {fileID: 2914604841386194871} - m_RootOrder: 6 + m_RootOrder: 5 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &4016391727385232918 GameObject: @@ -22658,7 +22573,7 @@ Transform: - {fileID: 8933642563102961015} - {fileID: 8281692494763879698} m_Father: {fileID: 2914604841386194871} - m_RootOrder: 4 + m_RootOrder: 3 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &4478159210902822598 GameObject: @@ -28473,6 +28388,7 @@ GameObject: serializedVersion: 6 m_Component: - component: {fileID: 8035163085009309331} + - component: {fileID: 624264686619249452} m_Layer: 0 m_Name: Timer m_TagString: Untagged @@ -28494,8 +28410,21 @@ Transform: m_Children: - {fileID: 3799935971409172323} m_Father: {fileID: 2914604841386194871} - m_RootOrder: 5 + m_RootOrder: 4 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &624264686619249452 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6447998919017828740} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 0b23b8169f8d2c54ebcd060a25262373, type: 3} + m_Name: + m_EditorClassIdentifier: + timerTrans: {fileID: 2908387998248567546} --- !u!1 &6766078402962959061 GameObject: m_ObjectHideFlags: 0 @@ -44210,7 +44139,7 @@ Transform: - {fileID: 1551030855227117807} - {fileID: 1359309479053844248} m_Father: {fileID: 2914604841386194871} - m_RootOrder: 1 + m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!95 &2616971115842020331 Animator: @@ -55082,7 +55011,7 @@ Transform: - {fileID: 7221935209627571158} - {fileID: 8225487404640725788} m_Father: {fileID: 2914604841386194871} - m_RootOrder: 3 + m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &9191679787071732581 GameObject: diff --git a/Assets/Scripts/Games/QuizShow/QSTimer.cs b/Assets/Scripts/Games/QuizShow/QSTimer.cs new file mode 100644 index 00000000..ef769a5a --- /dev/null +++ b/Assets/Scripts/Games/QuizShow/QSTimer.cs @@ -0,0 +1,30 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using HeavenStudio.Util; + +namespace HeavenStudio.Games.Scripts_QuizShow +{ + public class QSTimer : MonoBehaviour + { + [Header("Components")] + [SerializeField] private Transform timerTrans; + + private double startBeat = double.MaxValue; + private float length = 0; + + public void Init(double beat, float interval) + { + startBeat = beat; + length = interval; + Update(); + } + + private void Update() + { + var cond = Conductor.instance; + float normalizedBeat = cond.GetPositionFromBeat(startBeat, length); + if (normalizedBeat >= 0 && normalizedBeat <= 1) timerTrans.rotation = Quaternion.Euler(0, 0, normalizedBeat * -360); + } + } +} diff --git a/Assets/Scripts/Games/QuizShow/QSTimer.cs.meta b/Assets/Scripts/Games/QuizShow/QSTimer.cs.meta new file mode 100644 index 00000000..cd2a684b --- /dev/null +++ b/Assets/Scripts/Games/QuizShow/QSTimer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0b23b8169f8d2c54ebcd060a25262373 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Games/QuizShow/QuizShow.cs b/Assets/Scripts/Games/QuizShow/QuizShow.cs index e49594ce..13b75065 100644 --- a/Assets/Scripts/Games/QuizShow/QuizShow.cs +++ b/Assets/Scripts/Games/QuizShow/QuizShow.cs @@ -15,9 +15,18 @@ namespace HeavenStudio.Games.Loaders { new GameAction("intervalStart", "Start Interval") { - function = delegate {var e = eventCaller.currentEntity; QuizShow.instance.StartInterval(e.beat, e.length); }, + preFunction = delegate { var e = eventCaller.currentEntity; QuizShow.PreInterval(e.beat, e.length, + e["auto"], e["sound"], e["con"], e["visual"], e["audio"]); }, defaultLength = 8f, - resizable = true + resizable = true, + parameters = new List() + { + new Param("auto", true, "Auto Pass Turn"), + new Param("sound", true, "Play Time-Up Sound?", "Should the Time-Up sound play at the end of the interval?"), + new Param("con", false, "Consecutive", "Disables everything that happens at the end of the interval if ticked on."), + new Param("visual", true, "Stopwatch (Visual)", "Should the stopwatch visually appear?"), + new Param("audio", QuizShow.ClockAudio.Both, "Stopwatch (Audio)", "Should the sounds of the stopwatch play?") + } }, new GameAction("prepare", "Prepare Host Hands") { @@ -25,17 +34,14 @@ namespace HeavenStudio.Games.Loaders }, new GameAction("dPad", "DPad Press") { - function = delegate {var e = eventCaller.currentEntity; QuizShow.instance.HostPressButton(e.beat, true); }, defaultLength = 0.5f }, new GameAction("aButton", "A Button Press") { - function = delegate {var e = eventCaller.currentEntity; QuizShow.instance.HostPressButton(e.beat, false); }, defaultLength = 0.5f }, new GameAction("randomPresses", "Random Presses") { - function = delegate { var e = eventCaller.currentEntity; QuizShow.instance.RandomPress(e.beat, e.length, e["min"], e["max"], e["random"], e["con"]); }, parameters = new List() { new Param("min", new EntityTypes.Integer(0, 666, 0), "Minimum", "The minimum number of presses this block will do."), @@ -47,7 +53,7 @@ namespace HeavenStudio.Games.Loaders }, new GameAction("passTurn", "Pass Turn") { - function = delegate {var e = eventCaller.currentEntity; QuizShow.instance.PassTurn(e.beat, e.length, e["sound"], e["con"], e["visual"], e["audio"]); }, + preFunction = delegate {var e = eventCaller.currentEntity; QuizShow.PrePassTurn(e.beat, e["sound"], e["con"], e["visual"], e["audio"]); }, defaultLength = 1f, resizable = true, parameters = new List() @@ -112,6 +118,9 @@ namespace HeavenStudio.Games.Loaders namespace HeavenStudio.Games { + using Jukebox; + using Scripts_QuizShow; + public class QuizShow : Minigame { public enum ClockAudio @@ -152,7 +161,7 @@ namespace HeavenStudio.Games [SerializeField] Animator hostHead; [SerializeField] Animator signAnim; [SerializeField] Transform timerTransform; - [SerializeField] GameObject stopWatch; + [SerializeField] QSTimer stopWatchRef; [SerializeField] GameObject blackOut; [SerializeField] SpriteRenderer firstDigitSr; [SerializeField] SpriteRenderer secondDigitSr; @@ -167,54 +176,53 @@ namespace HeavenStudio.Games [SerializeField] List contestantNumberSprites = new List(); [SerializeField] List hostNumberSprites = new List(); [SerializeField] Sprite explodedCounter; - bool intervalStarted; bool shouldResetCount; bool doingConsectiveIntervals; - double intervalStartBeat; - double playerIntervalStartBeat; - float playerBeatInterval; - float beatInterval = 8f; int currentStage; bool shouldPrepareArms = true; bool contExploded; bool hostExploded; bool signExploded; - struct QueuedInput - { - public double beat; - public bool dpad; - } - static List queuedInputs = new List(); int pressCount; int countToMatch; + private double playerStartBeat = -1; + private float playerLength; public static QuizShow instance; - - void OnDestroy() + private struct RandomPress { - if (!Conductor.instance.isPlaying || Conductor.instance.isPaused) - { - if (queuedInputs.Count > 0) queuedInputs.Clear(); - } - foreach (var evt in scheduledInputs) - { - evt.Disable(); - } + public List randomPresses; + public double beat; } + private List randomPresses = new(); + void Awake() { instance = this; } + public override void OnPlay(double beat) + { + var allRandomEvents = EventCaller.GetAllInGameManagerList("quizShow", new string[] { "randomPresses" }); + foreach (var randomEvent in allRandomEvents) + { + randomPresses.Add(new RandomPress() + { + beat = randomEvent.beat, + randomPresses = GetRandomPress(randomEvent.beat, randomEvent.length, + randomEvent["min"], randomEvent["max"], randomEvent["random"], randomEvent["con"]) + }); + } + } + void Update() { var cond = Conductor.instance; if (cond.isPlaying && !cond.isPaused) { - float normalizedBeat = cond.GetPositionFromBeat(playerIntervalStartBeat, playerBeatInterval); - if (normalizedBeat >= 0 && normalizedBeat <= 1) + float normalizedBeat = cond.GetPositionFromBeat(playerStartBeat, playerLength); + if (normalizedBeat >= 0f && normalizedBeat <= 1f) { - timerTransform.rotation = Quaternion.Euler(0, 0, normalizedBeat * -360); if (PlayerInput.Pressed()) { ContesteePressButton(false); @@ -225,6 +233,37 @@ namespace HeavenStudio.Games } } } + + if (passedTurns.Count > 0) + { + foreach (var pass in passedTurns) + { + PassTurnStandalone(pass.beat, pass.timeUpSound, pass.consecutive, pass.visualClock, pass.audioClock); + } + passedTurns.Clear(); + } + } + + private List GetInputsBetweenBeat(double beat, double endBeat) + { + List allEvents = new(); + List nonRandoms = EventCaller.GetAllInGameManagerList("quizShow", new string[] { "dPad", "aButton" }).FindAll(x => x.beat >= beat && x.beat < endBeat); + List randoms = new(); + foreach (var rand in randomPresses) + { + if (rand.beat >= beat && rand.beat < endBeat) + { + randoms.AddRange(rand.randomPresses); + } + } + allEvents.AddRange(nonRandoms); + allEvents.AddRange(randoms); + return allEvents; + } + + private RiqEntity GetLastIntervalBeforeBeat(double beat) + { + return EventCaller.GetAllInGameManagerList("quizShow", new string[] { "intervalStart" }).FindLast(x => x.beat <= beat); } public void CountModifier(bool shouldReset) @@ -237,12 +276,12 @@ namespace HeavenStudio.Games currentStage = stage; } - public void RandomPress(double beat, float length, int min, int max, int whichButtons, bool consecutive) + private List GetRandomPress(double beat, float length, int min, int max, int whichButtons, bool consecutive) { - if (min > max) return; + if (min > max) return new(); int pressAmount = UnityEngine.Random.Range(min, max + 1); - if (pressAmount < 1) return; - List buttonEvents = new List(); + if (pressAmount < 1) return new(); + List buttonEntities = new(); if (consecutive) { for (int i = 0; i < pressAmount; i++) @@ -266,7 +305,11 @@ namespace HeavenStudio.Games break; } double spawnBeat = beat + i * length; - buttonEvents.Add(new BeatAction.Action(spawnBeat, delegate { HostPressButton(spawnBeat, dpad); })); + buttonEntities.Add(new RiqEntity(new RiqEntityData() + { + beat = spawnBeat, + datamodel = dpad ? "dPad" : "aButton" + })); } } else @@ -294,20 +337,19 @@ namespace HeavenStudio.Games break; } double spawnBeat = beat + i * length; - buttonEvents.Add(new BeatAction.Action(spawnBeat, delegate { HostPressButton(spawnBeat, dpad); })); + buttonEntities.Add(new RiqEntity(new RiqEntityData() + { + beat = spawnBeat, + datamodel = dpad ? "dPad" : "aButton" + })); pressAmount--; } } - - BeatAction.New(instance.gameObject, buttonEvents); + return buttonEntities; } public void HostPressButton(double beat, bool dpad) { - if (!intervalStarted) - { - StartInterval(beat, beatInterval); - } if (currentStage == 0) { contesteeHead.Play("ContesteeHeadIdle", -1, 0); @@ -317,7 +359,7 @@ namespace HeavenStudio.Games { hostHead.DoScaledAnimationAsync("HostStage" + currentStage.ToString(), 0.5f); } - SoundByte.PlayOneShotGame( dpad ? "quizShow/hostDPad" : "quizShow/hostA"); + SoundByte.PlayOneShotGame(dpad ? "quizShow/hostDPad" : "quizShow/hostA"); if (dpad) { hostRightArmAnim.DoScaledAnimationAsync("HostRightHit", 0.5f); @@ -326,11 +368,6 @@ namespace HeavenStudio.Games { hostLeftArmAnim.DoScaledAnimationAsync("HostLeftHit", 0.5f); } - queuedInputs.Add(new QueuedInput - { - beat = beat - intervalStartBeat, - dpad = dpad, - }); } public void HostPrepareHands() @@ -339,92 +376,223 @@ namespace HeavenStudio.Games instance.hostRightArmAnim.DoScaledAnimationAsync("HostPrepare", 0.5f); } - public void StartInterval(double beat, float interval) + public static void PreInterval(double beat, float interval, + bool autoPassTurn, bool timeUpSound, bool consecutive, bool visualClock, int audioClock) { - if (!intervalStarted) + if (GameManager.instance.currentGame == "quizShow") { - if (shouldPrepareArms) - { - hostLeftArmAnim.DoNormalizedAnimation("HostLeftPrepare", 1); - hostRightArmAnim.DoNormalizedAnimation("HostPrepare", 1); - contesteeHead.Play("ContesteeHeadIdle", 0, 0); - } - if (!doingConsectiveIntervals) pressCount = 0; - firstDigitSr.sprite = contestantNumberSprites[0]; - secondDigitSr.sprite = contestantNumberSprites[0]; - hostFirstDigitSr.sprite = hostNumberSprites[10]; - hostSecondDigitSr.sprite = hostNumberSprites[10]; - } - intervalStartBeat = beat; - beatInterval = interval; - intervalStarted = true; - } - - public void PassTurn(double beat, float length, bool timeUpSound, bool consecutive, bool visualClock, int audioClock) - { - if (queuedInputs.Count == 0) return; - if (shouldPrepareArms) - { - contesteeLeftArmAnim.DoScaledAnimationAsync("LeftPrepare", 0.5f); - contesteeRightArmAnim.DoScaledAnimationAsync("RIghtPrepare", 0.5f); - } - if (!consecutive) - { - hostLeftArmAnim.DoScaledAnimationAsync("HostLeftRest", 0.5f); - hostRightArmAnim.DoScaledAnimationAsync("HostRightRest", 0.5f); - } - shouldPrepareArms = false; - if (visualClock) stopWatch.SetActive(true); - intervalStarted = false; - if (doingConsectiveIntervals) - { - countToMatch += queuedInputs.Count; + instance.StartInterval(beat, interval, beat, autoPassTurn, timeUpSound, consecutive, visualClock, audioClock); } else { - countToMatch = queuedInputs.Count; + queuedIntervals.Add(new QueuedInterval() + { + beat = beat, + interval = interval, + autoPassTurn = autoPassTurn, + timeUpSound = timeUpSound, + consecutive = consecutive, + visualClock = visualClock, + audioClock = audioClock + }); + } + } + + private struct QueuedInterval + { + public double beat; + public float interval; + public bool autoPassTurn; + public bool timeUpSound; + public bool consecutive; + public bool visualClock; + public int audioClock; + } + + private static List queuedIntervals = new(); + + public override void OnGameSwitch(double beat) + { + if (queuedIntervals.Count > 0) + { + foreach (var interval in queuedIntervals) + { + StartInterval(interval.beat, interval.interval, beat, interval.autoPassTurn, + interval.timeUpSound, interval.consecutive, interval.visualClock, interval.audioClock); + } + queuedIntervals.Clear(); + } + var allRandomEvents = EventCaller.GetAllInGameManagerList("quizShow", new string[] { "randomPresses" }); + foreach (var randomEvent in allRandomEvents) + { + randomPresses.Add(new RandomPress() + { + beat = randomEvent.beat, + randomPresses = GetRandomPress(randomEvent.beat, randomEvent.length, + randomEvent["min"], randomEvent["max"], randomEvent["random"], randomEvent["con"]) + }); + } + } + + private void StartInterval(double beat, float interval, + double gameSwitchBeat, bool autoPassTurn, bool timeUpSound, bool consecutive, bool visualClock, int audioClock) + { + List actions = new() + { + new BeatAction.Action(beat, delegate + { + if (shouldPrepareArms) + { + hostLeftArmAnim.DoNormalizedAnimation("HostLeftPrepare", 1); + hostRightArmAnim.DoNormalizedAnimation("HostPrepare", 1); + contesteeHead.Play("ContesteeHeadIdle", 0, 0); + } + if (!doingConsectiveIntervals) pressCount = 0; + firstDigitSr.sprite = contestantNumberSprites[0]; + secondDigitSr.sprite = contestantNumberSprites[0]; + hostFirstDigitSr.sprite = hostNumberSprites[10]; + hostSecondDigitSr.sprite = hostNumberSprites[10]; + }) + }; + + var relevantInputs = GetInputsBetweenBeat(beat, beat + interval); + relevantInputs.Sort((x, y) => x.beat.CompareTo(y.beat)); + for (int i = 0; i < relevantInputs.Count; i++) + { + var input = relevantInputs[i]; + double inputBeat = input.beat; + if (inputBeat < gameSwitchBeat) continue; + bool isDpad = input.datamodel == "quizShow/dPad"; + bool isRandom = input.datamodel == "quizShow/randomPresses"; + actions.Add(new BeatAction.Action(inputBeat, delegate + { + HostPressButton(inputBeat, isDpad); + })); + } + BeatAction.New(gameObject, actions); + + if (autoPassTurn) + { + PassTurn(beat + interval, beat, interval, timeUpSound, consecutive, visualClock, audioClock); + } + } + + public static void PrePassTurn(double beat, bool timeUpSound, bool consecutive, bool visualClock, int audioClock) + { + if (GameManager.instance.currentGame == "quizShow") + { + instance.PassTurnStandalone(beat, timeUpSound, consecutive, visualClock, audioClock); + } + else + { + passedTurns.Add(new PassedTurn() + { + beat = beat, + timeUpSound = timeUpSound, + consecutive = consecutive, + visualClock = visualClock, + audioClock = audioClock + }); + } + } + + private struct PassedTurn + { + public double beat; + public bool timeUpSound; + public bool consecutive; + public bool visualClock; + public int audioClock; + } + + private static List passedTurns = new(); + + private void PassTurnStandalone(double beat, bool timeUpSound, bool consecutive, bool visualClock, int audioClock) + { + var lastInterval = GetLastIntervalBeforeBeat(beat); + if (lastInterval != null) + { + PassTurn(beat, lastInterval.beat, lastInterval.length, timeUpSound, consecutive, visualClock, audioClock); + } + } + + private void PassTurn(double beat, double intervalBeat, float intervalLength, bool timeUpSound, bool consecutive, bool visualClock, int audioClock) + { + playerStartBeat = beat + 1; + playerLength = intervalLength; + var relevantInputs = GetInputsBetweenBeat(intervalBeat, intervalBeat + intervalLength); + relevantInputs.Sort((x, y) => x.beat.CompareTo(y.beat)); + + for (int i = 0; i < relevantInputs.Count; i++) + { + double inputBeat = relevantInputs[i].beat - intervalBeat; + bool isDpad = relevantInputs[i].datamodel == "quizShow/dPad"; + if (isDpad) + { + ScheduleAutoplayInput(beat, 1 + inputBeat, InputType.DIRECTION_DOWN, AutoplayDPad, Nothing, Nothing); + } + else + { + ScheduleAutoplayInput(beat, 1 + inputBeat, InputType.STANDARD_DOWN, AutoplayAButton, Nothing, Nothing); + } + } + + if (doingConsectiveIntervals) + { + countToMatch += relevantInputs.Count; + } + else + { + countToMatch = relevantInputs.Count; } int hundredLoops = Mathf.FloorToInt(countToMatch / 100); countToMatch -= hundredLoops * 100; doingConsectiveIntervals = consecutive; - playerBeatInterval = beatInterval; - playerIntervalStartBeat = beat + length; float timeUpBeat = 0f; if (audioClock == (int)ClockAudio.Both || audioClock == (int)ClockAudio.Start) { - SoundByte.PlayOneShotGame("quizShow/timerStart"); + SoundByte.PlayOneShotGame("quizShow/timerStart", beat); timeUpBeat = 0.5f; } if (audioClock == (int)ClockAudio.End) timeUpBeat = 0.5f; - - BeatAction.New(instance.gameObject, new List() + QSTimer spawnedTimer = Instantiate(stopWatchRef, transform); + if (!visualClock) Destroy(spawnedTimer.gameObject); + List actions = new() { - new BeatAction.Action(beat + length + beatInterval, delegate - { - if (!consecutive) + new BeatAction.Action(beat, delegate + { + if (shouldPrepareArms) { - if (audioClock == (int)ClockAudio.Both || audioClock == (int)ClockAudio.End) SoundByte.PlayOneShotGame("quizShow/timerStop"); + contesteeLeftArmAnim.DoScaledAnimationAsync("LeftPrepare", 0.5f); + contesteeRightArmAnim.DoScaledAnimationAsync("RIghtPrepare", 0.5f); + } + if (!consecutive) + { + hostLeftArmAnim.DoScaledAnimationAsync("HostLeftRest", 0.5f); + hostRightArmAnim.DoScaledAnimationAsync("HostRightRest", 0.5f); + } + shouldPrepareArms = false; + if (visualClock) + { + spawnedTimer.gameObject.SetActive(true); + spawnedTimer.Init(beat + 1, intervalLength); + } + }), + new BeatAction.Action(beat + 1 + intervalLength, delegate + { + if (!consecutive) + { + if (audioClock == (int)ClockAudio.Both || audioClock == (int)ClockAudio.End) SoundByte.PlayOneShotGame("quizShow/timerStop"); contesteeLeftArmAnim.DoScaledAnimationAsync("LeftRest", 0.5f); contesteeRightArmAnim.DoScaledAnimationAsync("RightRest", 0.5f); shouldPrepareArms = true; - stopWatch.SetActive(false); } - } + if (visualClock) Destroy(spawnedTimer.gameObject); + } ), - new BeatAction.Action(beat + length + beatInterval + timeUpBeat, delegate { if (timeUpSound && !consecutive) SoundByte.PlayOneShotGame("quizShow/timeUp"); }) - }); - foreach (var input in queuedInputs) - { - if (input.dpad) - { - ScheduleAutoplayInput(beat, length + input.beat, InputType.DIRECTION_DOWN, AutoplayDPad, Nothing, Nothing); - } - else - { - ScheduleAutoplayInput(beat, length + input.beat, InputType.STANDARD_DOWN, AutoplayAButton, Nothing, Nothing); - } - } - queuedInputs.Clear(); + new BeatAction.Action(beat + 1 + intervalLength + timeUpBeat, delegate { if (timeUpSound && !consecutive) SoundByte.PlayOneShotGame("quizShow/timeUp"); }), + }; + BeatAction.New(instance.gameObject, actions); } void ContesteePressButton(bool dpad) diff --git a/Assets/Scripts/Games/Tambourine/Tambourine.cs b/Assets/Scripts/Games/Tambourine/Tambourine.cs index 53a8660c..635b8b31 100644 --- a/Assets/Scripts/Games/Tambourine/Tambourine.cs +++ b/Assets/Scripts/Games/Tambourine/Tambourine.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using UnityEngine; using DG.Tweening; +using Jukebox; namespace HeavenStudio.Games.Loaders { @@ -15,29 +16,30 @@ namespace HeavenStudio.Games.Loaders { new GameAction("beat intervals", "Start Interval") { - function = delegate {var e = eventCaller.currentEntity; Tambourine.instance.StartInterval(e.beat, e.length); }, + preFunction = delegate {var e = eventCaller.currentEntity; Tambourine.PreInterval(e.beat, e.length, e["auto"]); }, defaultLength = 8f, resizable = true, - priority = 1 + parameters = new List() + { + new Param("auto", true, "Auto Pass Turn") + } }, new GameAction("shake", "Shake") { - function = delegate {var e = eventCaller.currentEntity; Tambourine.instance.MonkeyInput(e.beat, false); }, defaultLength = 0.5f, - priority = 2 }, new GameAction("hit", "Hit") { - function = delegate {var e = eventCaller.currentEntity; Tambourine.instance.MonkeyInput(e.beat, true); }, defaultLength = 0.5f, - priority = 2 }, new GameAction("pass turn", "Pass Turn") { - function = delegate {var e = eventCaller.currentEntity; Tambourine.instance.PassTurn(e.beat, e.length); }, + preFunction = delegate + { + Tambourine.PrePassTurn(eventCaller.currentEntity.beat); + }, defaultLength = 1f, - resizable = true, - priority = 3 + preFunctionLength = 1f }, new GameAction("bop", "Bop") { @@ -113,9 +115,6 @@ namespace HeavenStudio.Games [SerializeField] Animator frogAnimator; [Header("Variables")] - bool intervalStarted; - double intervalStartBeat; - float beatInterval = 8f; float misses; bool frogPresent; bool monkeyGoBop; @@ -132,13 +131,6 @@ namespace HeavenStudio.Games None } - static List queuedInputs = new List(); - struct QueuedTambourineInput - { - public bool hit; - public double beatAwayFromStart; - } - public static Tambourine instance; void Awake() @@ -150,18 +142,6 @@ namespace HeavenStudio.Games monkeyAnimator.Play("MonkeyIdle", 0, 0); } - void OnDestroy() - { - if (!Conductor.instance.isPlaying || Conductor.instance.isPaused) - { - if (queuedInputs.Count > 0) queuedInputs.Clear(); - } - foreach (var evt in scheduledInputs) - { - evt.Disable(); - } - } - void Update() { if (Conductor.instance.ReportBeat(ref bop.lastReportedBeat, bop.startBeat % 1)) @@ -175,14 +155,6 @@ namespace HeavenStudio.Games handsAnimator.Play("Bop", 0, 0); } } - if (!Conductor.instance.isPlaying || Conductor.instance.isPaused) - { - if (queuedInputs.Count > 0) queuedInputs.Clear(); - } - if (!Conductor.instance.isPlaying && !Conductor.instance.isPaused && intervalStarted) - { - intervalStarted = false; - } if (PlayerInput.Pressed() && !IsExpectingInputNow(InputType.STANDARD_DOWN)) { handsAnimator.Play("Shake", 0, 0); @@ -190,7 +162,7 @@ namespace HeavenStudio.Games sweatAnimator.Play("Sweating", 0, 0); SummonFrog(); ScoreMiss(); - if (!intervalStarted) + if (!IntervalIsGoingOn()) { sadFace.SetActive(true); } @@ -202,77 +174,171 @@ namespace HeavenStudio.Games sweatAnimator.Play("Sweating", 0, 0); SummonFrog(); ScoreMiss(); - if (!intervalStarted) + if (!IntervalIsGoingOn()) { sadFace.SetActive(true); } } + + if (passedTurns.Count > 0) + { + foreach (var pass in passedTurns) + { + PassTurnStandalone(pass); + } + passedTurns.Clear(); + } } - public void StartInterval(double beat, float interval) + private bool IntervalIsGoingOn() { - intervalStartBeat = beat; - beatInterval = interval; - if (!intervalStarted) + double beat = Conductor.instance.songPositionInBeats; + return EventCaller.GetAllInGameManagerList("tambourine", new string[] { "beat intervals" }).Find(x => beat >= x.beat && beat < x.beat + x.length) != null; + } + + private List GetAllInputsBetweenBeat(double beat, double endBeat) + { + return EventCaller.GetAllInGameManagerList("tambourine", new string[] { "shake", "hit" }).FindAll(x => x.beat >= beat && x.beat < endBeat); + } + + public static void PreInterval(double beat, float interval, bool autoPassTurn) + { + if (GameManager.instance.currentGame == "tambourine") { - DesummonFrog(); - sadFace.SetActive(false); - //queuedInputs.Clear(); - misses = 0; - intervalStarted = true; + instance.StartInterval(beat, interval, beat, autoPassTurn); + } + else + { + queuedIntervals.Add(new QueuedInterval() + { + beat = beat, + interval = interval, + autoPassTurn = autoPassTurn + }); + } + } + + public override void OnGameSwitch(double beat) + { + if (queuedIntervals.Count > 0) + { + foreach (var interval in queuedIntervals) + { + StartInterval(interval.beat, interval.interval, beat, interval.autoPassTurn); + } + queuedIntervals.Clear(); + } + } + + private struct QueuedInterval + { + public double beat; + public float interval; + public bool autoPassTurn; + } + + private static List queuedIntervals = new(); + + private void StartInterval(double beat, float interval, double gameSwitchBeat, bool autoPassTurn) + { + List actions = new() + { + new BeatAction.Action(beat, delegate + { + DesummonFrog(); + sadFace.SetActive(false); + }) + }; + + var relevantInputs = GetAllInputsBetweenBeat(beat, beat + interval); + relevantInputs.Sort((x, y) => x.beat.CompareTo(y.beat)); + + for (int i = 0; i < relevantInputs.Count; i++) + { + bool isHit = relevantInputs[i].datamodel == "tambourine/hit"; + double inputBeat = relevantInputs[i].beat; + if (inputBeat >= gameSwitchBeat) + { + actions.Add(new BeatAction.Action(inputBeat, delegate + { + MonkeyInput(inputBeat, isHit); + })); + } + } + + BeatAction.New(gameObject, actions); + + if (autoPassTurn) + { + PassTurn(beat + interval, beat, interval); } } public void MonkeyInput(double beat, bool hit) { - if (!intervalStarted) - { - StartInterval(beat, beatInterval); - } if (hit) { - monkeyAnimator.Play("MonkeySmack", 0, 0); + monkeyAnimator.DoScaledAnimationAsync("MonkeySmack", 0.5f); SoundByte.PlayOneShotGame($"tambourine/monkey/hit/{UnityEngine.Random.Range(1, 6)}"); } else { - monkeyAnimator.Play("MonkeyShake", 0, 0); + monkeyAnimator.DoScaledAnimationAsync("MonkeyShake", 0.5f); SoundByte.PlayOneShotGame($"tambourine/monkey/shake/{UnityEngine.Random.Range(1, 6)}"); } - queuedInputs.Add(new QueuedTambourineInput() - { - hit = hit, - beatAwayFromStart = beat - intervalStartBeat, - }); } - public void PassTurn(double beat, float length) + private RiqEntity GetLastIntervalBeforeBeat(double beat) { - if (queuedInputs.Count == 0) return; - monkeyAnimator.Play("MonkeyPassTurn", 0, 0); - SoundByte.PlayOneShotGame($"tambourine/monkey/turnPass/{UnityEngine.Random.Range(1, 6)}"); - happyFace.SetActive(true); - intervalStarted = false; - BeatAction.New(instance.gameObject, new List() + return EventCaller.GetAllInGameManagerList("tambourine", new string[] { "beat intervals" }).FindLast(x => x.beat <= beat); + } + + public static void PrePassTurn(double beat) + { + if (GameManager.instance.currentGame == "tambourine") { - new BeatAction.Action(beat + 0.3f, delegate { happyFace.SetActive(false); }) - }); - foreach (var input in queuedInputs) - { - if (input.hit) - { - ScheduleInput(beat, length + input.beatAwayFromStart, InputType.STANDARD_ALT_DOWN , JustHit, Miss , Nothing); - } - else - { - ScheduleInput(beat, length + input.beatAwayFromStart, InputType.STANDARD_DOWN, JustShake, Miss, Nothing); - } - BeatAction.New(instance.gameObject, new List() - { - new BeatAction.Action(beat + length + input.beatAwayFromStart, delegate { Bop(beat + length + input.beatAwayFromStart, 1, (int)WhoBops.Monkey, (int)WhoBops.None); }) - }); + instance.PassTurnStandalone(beat); } - queuedInputs.Clear(); + else + { + passedTurns.Add(beat); + } + } + + private static List passedTurns = new(); + + private void PassTurnStandalone(double beat) + { + var lastInterval = GetLastIntervalBeforeBeat(beat); + if (lastInterval != null) PassTurn(beat, lastInterval.beat, lastInterval.length); + } + + private void PassTurn(double beat, double intervalBeat, float intervalLength) + { + SoundByte.PlayOneShotGame($"tambourine/monkey/turnPass/{UnityEngine.Random.Range(1, 6)}", beat); + List actions = new() + { + new BeatAction.Action(beat, delegate + { + monkeyAnimator.DoScaledAnimationAsync("MonkeyPassTurn", 0.5f); + happyFace.SetActive(true); + }), + new BeatAction.Action(beat + 0.3f, delegate { happyFace.SetActive(false); }) + }; + var relevantInputs = GetAllInputsBetweenBeat(intervalBeat, intervalBeat + intervalLength); + relevantInputs.Sort((x, y) => x.beat.CompareTo(y.beat)); + for (int i = 0; i < relevantInputs.Count; i++) + { + bool isHit = relevantInputs[i].datamodel == "tambourine/hit"; + double inputBeat = relevantInputs[i].beat - intervalBeat; + actions.Add(new BeatAction.Action(inputBeat, delegate + { + if (isHit) ScheduleInput(beat + 1, inputBeat, InputType.STANDARD_ALT_DOWN, JustHit, Miss, Nothing); + else ScheduleInput(beat + 1, inputBeat, InputType.STANDARD_DOWN, JustShake, Miss, Nothing); + Bop(beat + 1 + inputBeat, 1, (int)WhoBops.Monkey, (int)WhoBops.None); + })); + } + BeatAction.New(gameObject, actions); } public void Bop(double beat, float length, int whoBops, int whoBopsAuto) @@ -288,14 +354,14 @@ namespace HeavenStudio.Games switch (whoBops) { case (int) WhoBops.Monkey: - monkeyAnimator.Play("MonkeyBop", 0, 0); + monkeyAnimator.DoScaledAnimationAsync("MonkeyBop", 0.5f); break; case (int) WhoBops.Player: - handsAnimator.Play("Bop", 0, 0); + handsAnimator.DoScaledAnimationAsync("Bop", 0.5f); break; case (int) WhoBops.Both: - monkeyAnimator.Play("MonkeyBop", 0, 0); - handsAnimator.Play("Bop", 0, 0); + monkeyAnimator.DoScaledAnimationAsync("MonkeyBop", 0.5f); + handsAnimator.DoScaledAnimationAsync("Bop", 0.5f); break; default: break; @@ -330,12 +396,12 @@ namespace HeavenStudio.Games { if (state >= 1f || state <= -1f) { - handsAnimator.Play("Smack", 0, 0); + handsAnimator.DoScaledAnimationAsync("Smack", 0.5f); SoundByte.PlayOneShotGame($"tambourine/player/hit/{UnityEngine.Random.Range(1, 6)}"); SoundByte.PlayOneShotGame("tambourine/miss"); - sweatAnimator.Play("Sweating", 0, 0); + sweatAnimator.DoScaledAnimationAsync("Sweating", 0.5f); misses++; - if (!intervalStarted) + if (!IntervalIsGoingOn()) { sadFace.SetActive(true); } @@ -348,12 +414,12 @@ namespace HeavenStudio.Games { if (state >= 1f || state <= -1f) { - handsAnimator.Play("Shake", 0, 0); + handsAnimator.DoScaledAnimationAsync("Shake", 0.5f); SoundByte.PlayOneShotGame($"tambourine/player/shake/{UnityEngine.Random.Range(1, 6)}"); SoundByte.PlayOneShotGame("tambourine/miss"); - sweatAnimator.Play("Sweating", 0, 0); + sweatAnimator.DoScaledAnimationAsync("Sweating", 0.5f); misses++; - if (!intervalStarted) + if (!IntervalIsGoingOn()) { sadFace.SetActive(true); } @@ -367,12 +433,12 @@ namespace HeavenStudio.Games sadFace.SetActive(false); if (hit) { - handsAnimator.Play("Smack", 0, 0); + handsAnimator.DoScaledAnimationAsync("Smack", 0.5f); SoundByte.PlayOneShotGame($"tambourine/player/hit/{UnityEngine.Random.Range(1, 6)}"); } else { - handsAnimator.Play("Shake", 0, 0); + handsAnimator.DoScaledAnimationAsync("Shake", 0.5f); SoundByte.PlayOneShotGame($"tambourine/player/shake/{UnityEngine.Random.Range(1, 6)}"); } } @@ -380,9 +446,9 @@ namespace HeavenStudio.Games public void Miss(PlayerActionEvent caller) { SummonFrog(); - sweatAnimator.Play("Sweating", 0, 0); + sweatAnimator.DoScaledAnimationAsync("Sweating", 0.5f); misses++; - if (!intervalStarted) + if (!IntervalIsGoingOn()) { sadFace.SetActive(true); }