diff --git a/Assets/Resources/Games/nailCarpenter.prefab b/Assets/Resources/Games/nailCarpenter.prefab index 4ebb98ed7..efb549ac3 100644 --- a/Assets/Resources/Games/nailCarpenter.prefab +++ b/Assets/Resources/Games/nailCarpenter.prefab @@ -634,6 +634,50 @@ MonoBehaviour: m_EditorClassIdentifier: SoundSequences: [] scheduledInputs: [] + puddingPattern: + - beat: 0 + type: 2 + - beat: 0.5 + type: 0 + - beat: 1 + type: 8 + cherryPattern: + - beat: 0 + type: 2 + - beat: 0.5 + type: 0 + - beat: 1 + type: 0 + - beat: 1.5 + type: 0 + - beat: 2 + type: 8 + cakePattern: + - beat: 0 + type: 2 + - beat: 0.5 + type: 0 + - beat: 1 + type: 3 + - beat: 1.25 + type: 0 + - beat: 1.75 + type: 0 + - beat: 2 + type: 8 + cakeLongPattern: + - beat: 0 + type: 2 + - beat: 0.5 + type: 0 + - beat: 1 + type: 9 + - beat: 1.5 + type: 1 + - beat: 2 + type: 8 + scrollMetresPerBeat: -4.5 + boardWidth: 19.2 baseNail: {fileID: 7504610799131467556} baseLongNail: {fileID: 4122843866948130824} baseSweet: {fileID: 7846700753925185796} @@ -1168,6 +1212,8 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: targetBeat: 0 + targetX: 0 + metresPerSecond: 0 nailAnim: {fileID: 3330987451715863783} --- !u!1 &4314335590168154470 GameObject: @@ -1899,6 +1945,8 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: targetBeat: 0 + targetX: 0 + metresPerSecond: 0 nailAnim: {fileID: 845294389825628466} --- !u!1 &7846700753925185796 GameObject: @@ -1946,6 +1994,8 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: targetBeat: 0 + targetX: 0 + metresPerSecond: 0 sweetType: 0 sweetAnim: {fileID: 4107796134930477793} --- !u!1 &7940810347463623349 @@ -2174,7 +2224,7 @@ Transform: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 8791741134951954224} m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 2.635, y: 0, z: 0} + m_LocalPosition: {x: 1.9, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] diff --git a/Assets/Scripts/Games/NailCarpenter/LongNail.cs b/Assets/Scripts/Games/NailCarpenter/LongNail.cs index 3e06bb1ec..aae2c5cec 100644 --- a/Assets/Scripts/Games/NailCarpenter/LongNail.cs +++ b/Assets/Scripts/Games/NailCarpenter/LongNail.cs @@ -13,6 +13,8 @@ namespace HeavenStudio.Games.Scripts_NailCarpenter public class LongNail : MonoBehaviour { public double targetBeat; + public float targetX; + public float metresPerSecond; public Animator nailAnim; private NailCarpenter game; @@ -20,13 +22,14 @@ namespace HeavenStudio.Games.Scripts_NailCarpenter public void Init() { game = NailCarpenter.instance; - - game.ScheduleInput(targetBeat, 1f, NailCarpenter.InputAction_AltStart, HammmerJust, HammmerMiss, Empty); + + game.ScheduleInput(targetBeat, 0, NailCarpenter.InputAction_AltPress, HammmerJust, HammmerMiss, null); // wrongInput if (PlayerInput.CurrentControlStyle != InputController.ControlStyles.Touch) { - game.ScheduleUserInput(targetBeat, 1f, NailCarpenter.InputAction_RegPress, weakHammmerJust, Empty, Empty); + game.ScheduleUserInput(targetBeat, 0, NailCarpenter.InputAction_RegPress, WeakHammmerJust, null, null); } + Update(); } private void HammmerJust(PlayerActionEvent caller, float state) @@ -44,7 +47,7 @@ namespace HeavenStudio.Games.Scripts_NailCarpenter game.EyeAnim.DoScaledAnimationAsync("eyeSmile", 0.25f); } - private void weakHammmerJust(PlayerActionEvent caller, float state) + private void WeakHammmerJust(PlayerActionEvent caller, float state) { game.ScoreMiss(); game.Carpenter.DoScaledAnimationAsync("carpenterHit", 0.25f); @@ -64,8 +67,6 @@ namespace HeavenStudio.Games.Scripts_NailCarpenter game.EyeAnim.DoScaledAnimationAsync("eyeBlink", 0.25f); } - private void Empty(PlayerActionEvent caller) { } - private void Update() { var cond = Conductor.instance; @@ -73,7 +74,10 @@ namespace HeavenStudio.Games.Scripts_NailCarpenter if (cond.isPlaying && !cond.isPaused) { double beat = cond.songPositionInBeats; - if (targetBeat != double.MinValue) + Vector3 pos = transform.position; + pos.x = targetX + (float)((beat - targetBeat) * metresPerSecond); + transform.position = pos; + if (targetBeat != double.MinValue) { if (beat >= targetBeat + 9) Destroy(gameObject); } diff --git a/Assets/Scripts/Games/NailCarpenter/Nail.cs b/Assets/Scripts/Games/NailCarpenter/Nail.cs index cc54ce344..6203d2e0b 100644 --- a/Assets/Scripts/Games/NailCarpenter/Nail.cs +++ b/Assets/Scripts/Games/NailCarpenter/Nail.cs @@ -13,6 +13,8 @@ namespace HeavenStudio.Games.Scripts_NailCarpenter public class Nail : MonoBehaviour { public double targetBeat; + public float targetX; + public float metresPerSecond; public Animator nailAnim; private NailCarpenter game; @@ -20,13 +22,14 @@ namespace HeavenStudio.Games.Scripts_NailCarpenter public void Init() { game = NailCarpenter.instance; - - game.ScheduleInput(targetBeat, 0, NailCarpenter.InputAction_RegPress, HammmerJust, HammmerMiss, Empty); + + game.ScheduleInput(targetBeat, 0, NailCarpenter.InputAction_RegPress, HammmerJust, HammmerMiss, null); //wrong input if (PlayerInput.CurrentControlStyle != InputController.ControlStyles.Touch) { - game.ScheduleUserInput(targetBeat, 0, NailCarpenter.InputAction_AltStart, strongHammmerJust, Empty, Empty); + game.ScheduleUserInput(targetBeat, 0, NailCarpenter.InputAction_AltPress, strongHammmerJust, null, null); } + Update(); } private void HammmerJust(PlayerActionEvent caller, float state) @@ -62,8 +65,6 @@ namespace HeavenStudio.Games.Scripts_NailCarpenter game.EyeAnim.DoScaledAnimationAsync("eyeBlink", 0.25f); } - private void Empty(PlayerActionEvent caller) { } - private void Update() { var cond = Conductor.instance; @@ -71,7 +72,10 @@ namespace HeavenStudio.Games.Scripts_NailCarpenter if (cond.isPlaying && !cond.isPaused) { double beat = cond.songPositionInBeats; - if (targetBeat != double.MinValue) + Vector3 pos = transform.position; + pos.x = targetX + (float)((beat - targetBeat) * metresPerSecond); + transform.position = pos; + if (targetBeat != double.MinValue) { if (beat >= targetBeat + 9) Destroy(gameObject); } diff --git a/Assets/Scripts/Games/NailCarpenter/NailCarpenter.cs b/Assets/Scripts/Games/NailCarpenter/NailCarpenter.cs index 0187272c5..9b18d7364 100644 --- a/Assets/Scripts/Games/NailCarpenter/NailCarpenter.cs +++ b/Assets/Scripts/Games/NailCarpenter/NailCarpenter.cs @@ -16,33 +16,29 @@ namespace HeavenStudio.Games.Loaders { new GameAction("puddingNail", "Pudding Nail") { - function = delegate {NailCarpenter.instance.PlaySound();}, defaultLength = 8f, resizable = true }, new GameAction("cherryNail", "Cherry Nail") { - function = delegate {NailCarpenter.instance.PlaySound();}, defaultLength = 4f, resizable = true }, new GameAction("cakeNail", "Cake Nail") { - function = delegate {NailCarpenter.instance.PlaySound();}, defaultLength = 4f, resizable = true }, new GameAction("cakeLongNail", "Cake Long Nail") { - function = delegate {NailCarpenter.instance.PlaySound();}, defaultLength = 4f, resizable = true }, new GameAction("slideFusuma", "Slide Shoji") { function = delegate { - var e = eventCaller.currentEntity; - NailCarpenter.instance.SlideShoji(e.beat, e.length, e["fillRatio"], e["ease"], e["mute"]); + var e = eventCaller.currentEntity; + NailCarpenter.instance.SlideShoji(e.beat, e.length, e["fillRatio"], e["ease"], e["mute"]); }, defaultLength = 1f, resizable = true, @@ -53,7 +49,7 @@ namespace HeavenStudio.Games.Loaders new Param("mute", false, "Mute", "Toggle if the cue should be muted.") } }, - + }, new List() { "pco", "normal" }, "pconail", "en", @@ -65,10 +61,59 @@ namespace HeavenStudio.Games.Loaders namespace HeavenStudio.Games { + using System.Diagnostics; + using System.Linq; using Scripts_NailCarpenter; public class NailCarpenter : Minigame { + const double PATTERN_SEEK_TIME = 8.0; + + [Serializable] + public struct ObjectPatternItem + { + public double beat; + public ObjectType type; + } + + public enum ObjectType + { + Nail, + LongNail, + Sweet, + ForceCherry, + ForcePudding, + ForceCherryPudding, + ForceShortCake, + ForceLayerCake, + None, + LongCharge + } + + struct ScheduledPattern + { + public double beat; + public double length; + public PatternType type; + } + + enum PatternType + { + Pudding, + Cherry, + Cake, + CakeLong, + None + } + + + [SerializeField] ObjectPatternItem[] puddingPattern; + [SerializeField] ObjectPatternItem[] cherryPattern; + [SerializeField] ObjectPatternItem[] cakePattern; + [SerializeField] ObjectPatternItem[] cakeLongPattern; + [SerializeField] float scrollMetresPerBeat = 4f; + [SerializeField] float boardWidth = 19.2f; + public GameObject baseNail; public GameObject baseLongNail; public GameObject baseSweet; @@ -81,15 +126,12 @@ namespace HeavenStudio.Games public Transform nailHolder; public Transform boardTrans; public Transform shojiTrans; - const float nailDistance = -4f; - const float boardWidth = 19.2f; - float scrollRate => nailDistance / (Conductor.instance.pitchedSecPerBeat * 2f); private bool missed; private bool hasSlurped; const int IAAltDownCat = IAMAXCAT; - const int IAAltUpCat = IAMAXCAT + 1; + const int IASweetsCat = IAMAXCAT + 1; protected static bool IA_PadAltPress(out double dt) { @@ -102,37 +144,43 @@ namespace HeavenStudio.Games protected static bool IA_TouchRegularPress(out double dt) { - return PlayerInput.GetTouchDown(InputController.ActionsTouch.Tap, out dt); + return PlayerInput.GetTouchDown(InputController.ActionsTouch.Tap, out dt) + && !instance.IsExpectingInputNow(InputAction_AltPress); } protected static bool IA_TouchAltPress(out double dt) { return PlayerInput.GetTouchDown(InputController.ActionsTouch.Tap, out dt) - && instance.IsExpectingInputNow(InputAction_AltStart) + && instance.IsExpectingInputNow(InputAction_AltPress) && !instance.IsExpectingInputNow(InputAction_RegPress); } - protected static bool IA_PadAltRelease(out double dt) + protected static bool IA_PadSweetsCheck(out double dt) { - return PlayerInput.GetPadUp(InputController.ActionsPad.South, out dt); + return (PlayerInput.GetPadDown(InputController.ActionsPad.South, out dt) + || PlayerInput.GetPadDown(InputController.ActionsPad.East, out dt)) + && !(instance.IsExpectingInputNow(InputAction_RegPress) || instance.IsExpectingInputNow(InputAction_AltPress)); } - protected static bool IA_BatonAltRelease(out double dt) + protected static bool IA_BatonSweetsCheck(out double dt) { - return PlayerInput.GetSqueezeUp(out dt); + return (PlayerInput.GetBatonDown(InputController.ActionsBaton.Face, out dt) + || PlayerInput.GetSqueezeDown(out dt)) + && !(instance.IsExpectingInputNow(InputAction_RegPress) || instance.IsExpectingInputNow(InputAction_AltPress)); + } + protected static bool IA_TouchSweetsCheck(out double dt) + { + return PlayerInput.GetTouchDown(InputController.ActionsTouch.Tap, out dt) + && !(instance.IsExpectingInputNow(InputAction_RegPress) || instance.IsExpectingInputNow(InputAction_AltPress)); } - public static PlayerInput.InputAction InputAction_RegPress = - new("PcoNailRegStart", new int[] { IAPressCat, IAPressCat, IAPressCat }, + new("PcoNailRegStart", new int[] { IAPressCat, IAPressCat, IAPressCat }, IA_PadBasicPress, IA_TouchRegularPress, IA_BatonBasicPress); - public static PlayerInput.InputAction InputAction_AltStart = + public static PlayerInput.InputAction InputAction_AltPress = new("PcoNailAltStart", new int[] { IAAltDownCat, IAAltDownCat, IAAltDownCat }, IA_PadAltPress, IA_TouchAltPress, IA_BatonAltPress); - public static PlayerInput.InputAction InputAction_AltFinish = - new("PcoNailAltFinish", new int[] { IAAltUpCat, IAFlickCat, IAAltUpCat }, - IA_PadAltRelease, IA_TouchFlick, IA_BatonAltRelease); - public static PlayerInput.InputAction InputAction_TouchRelease = - new("PcoNailTouchRelease", new int[] { IAEmptyCat, IAReleaseCat, IAEmptyCat }, - IA_Empty, IA_TouchBasicRelease, IA_Empty); + public static PlayerInput.InputAction InputAction_SweetsHit = + new("PcoNailSweetsHit", new int[] { IASweetsCat, IASweetsCat, IASweetsCat }, + IA_PadSweetsCheck, IA_TouchSweetsCheck, IA_BatonSweetsCheck); public static NailCarpenter instance; @@ -142,185 +190,89 @@ namespace HeavenStudio.Games instance = this; } + List scheduledPatterns = new List(); + double patternStartBeat, gameStartBeat; + PatternType patternType, lastPatternType; + int patternIndex; + double slideBeat = double.MaxValue; double slideLength; + double cachedPatternLengthPudding, cachedPatternLengthCherry, cachedPatternLengthCake, cachedPatternLengthCakeLong; Util.EasingFunction.Ease slideEase; float slideRatioLast = 0, slideRatioNext = 0; + void Start() + { + if (!conductor.isPlaying) return; + UpdatePatterns(); + } void Update() { - var cond = Conductor.instance; - var currentBeat = cond.songPositionInBeatsAsDouble; + var currentBeat = conductor.songPositionInBeatsAsDouble; - if (!cond.isPlaying) return; - - // Debug.Log(newBeat); + if (!conductor.isPlaying) return; if (PlayerInput.GetIsAction(InputAction_RegPress) && !IsExpectingInputNow(InputAction_RegPress)) { + ScoreMiss(); SoundByte.PlayOneShot("miss"); Carpenter.DoScaledAnimationAsync("carpenterHit", 0.25f); hasSlurped = false; - // ScoreMiss(); } - if (PlayerInput.GetIsAction(InputAction_AltStart) && !IsExpectingInputNow(InputAction_AltStart)) + if (PlayerInput.GetIsAction(InputAction_AltPress) && !IsExpectingInputNow(InputAction_AltPress)) { + ScoreMiss(); SoundByte.PlayOneShot("miss"); Carpenter.DoScaledAnimationAsync("carpenterHit", 0.25f); hasSlurped = false; - // ScoreMiss(); } - // Object scroll. - var scrollPos = scrollingHolder.localPosition; - var newScrollX = scrollPos.x + (scrollRate * Time.deltaTime); - scrollingHolder.localPosition = new Vector3(newScrollX, scrollPos.y, scrollPos.z); - // Board scroll. var boardPos = boardTrans.localPosition; - var newBoardX = boardPos.x + (scrollRate * Time.deltaTime); + var newBoardX = currentBeat * scrollMetresPerBeat; newBoardX %= boardWidth; - boardTrans.localPosition = new Vector3(newBoardX, boardPos.y, boardPos.z); + boardTrans.localPosition = new Vector3((float)newBoardX, boardPos.y, boardPos.z); + UpdatePatterns(); UpdateShoji(currentBeat); } public override void OnGameSwitch(double beat) { - double startBeat; + cachedPatternLengthPudding = puddingPattern[^1].beat; + cachedPatternLengthCherry = cherryPattern[^1].beat; + cachedPatternLengthCake = cakePattern[^1].beat; + cachedPatternLengthCakeLong = cakeLongPattern[^1].beat; + double endBeat = double.MaxValue; - var entities = GameManager.instance.Beatmap.Entities; + var entities = gameManager.Beatmap.Entities; - startBeat = beat; + gameStartBeat = beat; + patternStartBeat = gameStartBeat; // find out when the next game switch (or remix end) happens - RiqEntity firstEnd = entities.Find(c => (c.datamodel.StartsWith("gameManager/switchGame") || c.datamodel.Equals("gameManager/end")) && c.beat > startBeat); - endBeat = firstEnd?.beat ?? double.MaxValue; + RiqEntity firstEnd = entities.Find(c => (c.datamodel.StartsWith("gameManager/switchGame") || c.datamodel.Equals("gameManager/end")) && c.beat > gameStartBeat); + endBeat = firstEnd?.beat ?? endBeat; - // Nail events. - List pudNailEvents = entities.FindAll(v => v.datamodel == "nailCarpenter/puddingNail"); - List chrNailEvents = entities.FindAll(v => v.datamodel == "nailCarpenter/cherryNail"); - List cakeNailEvents = entities.FindAll(v => v.datamodel == "nailCarpenter/cakeNail"); - List cklNailEvents = entities.FindAll(v => v.datamodel == "nailCarpenter/cakeLongNail"); - - var cherryTargetBeats = new List(){}; - - // Spawn cake and nail. - for (int i = 0; i < cakeNailEvents.Count; i++) { - var nailBeat = cakeNailEvents[i].beat; - var nailLength = cakeNailEvents[i].length; - - // Only consider nailgie events that aren't past the start point. - if (startBeat <= nailBeat + nailLength) { - int nailInEvent = Mathf.CeilToInt(nailLength + 2) / 4; - - for (int b = 0; b < nailInEvent; b++) + List events = entities.FindAll(v => (v.datamodel is "nailCarpenter/puddingNail" or "nailCarpenter/cherryNail" or "nailCarpenter/cakeNail" or "nailCarpenter/cakeLongNail") && v.beat >= gameStartBeat && v.beat < endBeat); + scheduledPatterns.Clear(); + patternIndex = 0; + foreach (var evt in events) + { + var pattern = new ScheduledPattern + { + beat = evt.beat, + length = evt.length, + type = evt.datamodel switch { - var targetNailBeat = nailBeat + (4f * b); - if (startBeat <= targetNailBeat && targetNailBeat < endBeat) - { - sounds.Add(new MultiSound.Sound("nailCarpenter/alarm", targetNailBeat)); - BeatAction.New(instance, new List() - { - new BeatAction.Action(targetNailBeat, delegate - { - EffectExclamRed.DoScaledAnimationAsync("exclamAppear", 0.25f); - }) - }); - SpawnSweet(targetNailBeat, startBeat, - (b==0 ? Sweet.sweetsType.ShortCake : Sweet.sweetsType.Cherry)); - SpawnNail(targetNailBeat+1f, startBeat); - SpawnSweet(targetNailBeat+2f, startBeat, Sweet.sweetsType.Cherry); - SpawnNail(targetNailBeat+2.5f, startBeat); - SpawnNail(targetNailBeat+3.5f, startBeat); - } + "nailCarpenter/puddingNail" => PatternType.Pudding, + "nailCarpenter/cherryNail" => PatternType.Cherry, + "nailCarpenter/cakeNail" => PatternType.Cake, + "nailCarpenter/cakeLongNail" => PatternType.CakeLong, + _ => throw new NotImplementedException() } - cherryTargetBeats.Add(nailBeat + 4f * nailInEvent); - } - } - // Spawn pudding and nail. - for (int i = 0; i < pudNailEvents.Count; i++) { - var nailBeat = pudNailEvents[i].beat; - var nailLength = pudNailEvents[i].length; - - // Only consider nailgie events that aren't past the start point. - if (startBeat <= nailBeat + nailLength) { - int nailInEvent = Mathf.CeilToInt(nailLength)/2; - for (int b = 0; b < nailInEvent; b++) - { - var targetNailBeat = nailBeat + (2f * b); - - if (startBeat <= targetNailBeat && targetNailBeat < endBeat) - { - sounds.Add(new MultiSound.Sound("nailCarpenter/one", targetNailBeat)); - SpawnSweet(targetNailBeat, startBeat, - (IsInRange(cherryTargetBeats, targetNailBeat) ? Sweet.sweetsType.Cherry : - Sweet.sweetsType.Pudding)); - SpawnNail(targetNailBeat+1f, startBeat); - } - } - } - } - // Spawn cherrypudding and nail. - for (int i = 0; i < chrNailEvents.Count; i++) { - var nailBeat = chrNailEvents[i].beat; - var nailLength = chrNailEvents[i].length; - - // Only consider nailgie events that aren't past the start point. - if (startBeat <= nailBeat + nailLength) { - int nailInEvent = Mathf.CeilToInt(nailLength + 1f) / 4; - - for (int b = 0; b < nailInEvent; b++) - { - var targetNailBeat = nailBeat + (4f * b); - if (startBeat <= targetNailBeat && targetNailBeat < endBeat) - { - sounds.Add(new MultiSound.Sound("nailCarpenter/three", targetNailBeat)); - SpawnSweet(targetNailBeat, startBeat, - (IsInRange(cherryTargetBeats, targetNailBeat) ? Sweet.sweetsType.Cherry : - Sweet.sweetsType.CherryPudding)); - SpawnNail(targetNailBeat+1f, startBeat); - SpawnNail(targetNailBeat+2f, startBeat); - SpawnNail(targetNailBeat+3f, startBeat); - } - } - } - } - // Spawn long nail. - for (int i = 0; i < cklNailEvents.Count; i++) { - var nailBeat = cklNailEvents[i].beat; - var nailLength = cklNailEvents[i].length; - - // Only consider nailgie events that aren't past the start point. - if (startBeat <= nailBeat + nailLength) { - int nailInEvent = Mathf.CeilToInt(nailLength + 2) / 4; - - for (int b = 0; b < nailInEvent; b++) - { - var targetNailBeat = nailBeat + (4f * b); - if (startBeat <= targetNailBeat && targetNailBeat < endBeat) - { - sounds.Add(new MultiSound.Sound("nailCarpenter/signal1", targetNailBeat)); - sounds.Add(new MultiSound.Sound("nailCarpenter/signal2", targetNailBeat+2f)); - BeatAction.New(instance, new List() - { - new BeatAction.Action(targetNailBeat, delegate - { - EffectExclamBlue.DoScaledAnimationAsync("exclamAppear", 0.25f); - }), - new BeatAction.Action(targetNailBeat+1.5f, delegate - { - Carpenter.DoScaledAnimationAsync("carpenterArmUp", 0.25f); - }), - }); - SpawnSweet(targetNailBeat, startBeat, - (IsInRange(cherryTargetBeats, targetNailBeat) ? Sweet.sweetsType.Cherry : - Sweet.sweetsType.LayerCake)); - SpawnNail(targetNailBeat+1f, startBeat); - SpawnLongNail(targetNailBeat+2f, startBeat); - } - } - } + }; + scheduledPatterns.Add(pattern); } } @@ -329,21 +281,42 @@ namespace HeavenStudio.Games OnGameSwitch(beat); } + void UpdatePatterns() + { + double beat = conductor.songPositionInBeatsAsDouble; + while (patternStartBeat < beat + PATTERN_SEEK_TIME) + { + if (patternIndex < scheduledPatterns.Count) + { + var pattern = scheduledPatterns[patternIndex]; + if (pattern.beat + pattern.length < patternStartBeat) continue; + SpawnPattern(pattern.beat, pattern.length, pattern.type); + patternStartBeat += pattern.length; + patternIndex++; + } + else + { + break; + } + } + } + public void SlideShoji(double beat, double length, float fillRatio, int ease, bool mute) { - if (!mute) MultiSound.Play(new MultiSound.Sound[]{ new MultiSound.Sound("nailCarpenter/open", beat)}); + if (!mute) SoundByte.PlayOneShotGame("nailCarpenter/open", beat, forcePlay: true); slideBeat = beat; slideLength = length; slideEase = (Util.EasingFunction.Ease)ease; slideRatioLast = slideRatioNext; slideRatioNext = fillRatio; } + void UpdateShoji(double beat) { if (beat >= slideBeat) { - float slideLast = 17.8f *(1-slideRatioLast); - float slideNext = 17.8f *(1-slideRatioNext); + float slideLast = 17.8f * (1 - slideRatioLast); + float slideNext = 17.8f * (1 - slideRatioNext); Util.EasingFunction.Function func = Util.EasingFunction.GetEasingFunction(slideEase); float slideProg = Conductor.instance.GetPositionFromBeat(slideBeat, slideLength, true); slideProg = Mathf.Clamp01(slideProg); @@ -352,14 +325,139 @@ namespace HeavenStudio.Games } } + private void SpawnPattern(double beat, double length, PatternType pattern) + { + if (pattern == PatternType.None) return; + double patternLength = pattern switch + { + PatternType.Pudding => cachedPatternLengthPudding, + PatternType.Cherry => cachedPatternLengthCherry, + PatternType.Cake => cachedPatternLengthCake, + PatternType.CakeLong => cachedPatternLengthCakeLong, + _ => throw new NotImplementedException() + }; + patternType = pattern; + int patternIterations = (int)Math.Ceiling(length / patternLength); + for (int i = 0; i < patternIterations; i++) + { + SpawnPatternSegment(beat + (patternLength * i), gameStartBeat, pattern switch + { + PatternType.Pudding => puddingPattern, + PatternType.Cherry => cherryPattern, + PatternType.Cake => cakePattern, + PatternType.CakeLong => cakeLongPattern, + _ => throw new NotImplementedException() + }); + lastPatternType = patternType; + } + } + + private void SpawnPatternSegment(double beat, double startbeat, ObjectPatternItem[] pattern) + { + foreach (var item in pattern) + { + double itemBeat = beat + item.beat; + switch (item.type) + { + case ObjectType.LongCharge: + SoundByte.PlayOneShotGame("nailCarpenter/signal2", itemBeat, forcePlay: true); + BeatAction.New(instance, new List() + { + new BeatAction.Action(itemBeat, delegate + { + Carpenter.DoScaledAnimationAsync("carpenterArmUp", 0.25f); + }), + }); + break; + case ObjectType.Nail: + SpawnNail(itemBeat, startbeat); + break; + case ObjectType.LongNail: + SpawnLongNail(itemBeat, startbeat); + break; + case ObjectType.Sweet: + // dynamically determine sweet based on pattern and last pattern + Sweet.sweetsType sweetType = Sweet.sweetsType.None; + switch (patternType) + { + case PatternType.Pudding: + SoundByte.PlayOneShotGame("nailCarpenter/one", itemBeat, forcePlay: true); + sweetType = Sweet.sweetsType.Pudding; + break; + case PatternType.Cherry: + SoundByte.PlayOneShotGame("nailCarpenter/three", itemBeat, forcePlay: true); + sweetType = Sweet.sweetsType.CherryPudding; + break; + case PatternType.Cake: + SoundByte.PlayOneShotGame("nailCarpenter/alarm", itemBeat, forcePlay: true); + sweetType = Sweet.sweetsType.ShortCake; + BeatAction.New(instance, new List() + { + new BeatAction.Action(itemBeat, delegate + { + EffectExclamRed.DoScaledAnimationAsync("exclamAppear", 0.25f); + }) + }); + break; + case PatternType.CakeLong: + SoundByte.PlayOneShotGame("nailCarpenter/signal1", itemBeat, forcePlay: true); + sweetType = Sweet.sweetsType.LayerCake; + BeatAction.New(instance, new List() + { + new BeatAction.Action(itemBeat, delegate + { + EffectExclamBlue.DoScaledAnimationAsync("exclamAppear", 0.25f); + }), + }); + break; + default: + break; + } + if (lastPatternType == PatternType.Cake) + { + SpawnSweet(itemBeat, startbeat, Sweet.sweetsType.Cherry); + } + else if (sweetType != Sweet.sweetsType.None) + { + SpawnSweet(itemBeat, startbeat, sweetType); + } + break; + case ObjectType.ForceCherry: + SpawnSweet(itemBeat, startbeat, Sweet.sweetsType.Cherry); + break; + case ObjectType.ForcePudding: + SoundByte.PlayOneShotGame("nailCarpenter/one", itemBeat); + SpawnSweet(itemBeat, startbeat, Sweet.sweetsType.Pudding); + break; + case ObjectType.ForceCherryPudding: + SoundByte.PlayOneShotGame("nailCarpenter/three", itemBeat, forcePlay: true); + SpawnSweet(itemBeat, startbeat, Sweet.sweetsType.CherryPudding); + break; + case ObjectType.ForceShortCake: + SoundByte.PlayOneShotGame("nailCarpenter/alarm", itemBeat, forcePlay: true); + SpawnSweet(itemBeat, startbeat, Sweet.sweetsType.ShortCake); + break; + case ObjectType.ForceLayerCake: + SoundByte.PlayOneShotGame("nailCarpenter/signal1", itemBeat, forcePlay: true); + SoundByte.PlayOneShotGame("nailCarpenter/signal2", itemBeat + 1, forcePlay: true); + SpawnSweet(itemBeat, startbeat, Sweet.sweetsType.LayerCake); + break; + default: + break; + } + } + } + private void SpawnNail(double beat, double startBeat) { var newNail = Instantiate(baseNail, nailHolder).GetComponent(); newNail.targetBeat = beat; + newNail.targetX = nailHolder.position.x; + newNail.metresPerSecond = scrollMetresPerBeat; - var nailX = (beat - startBeat) * -nailDistance / 2f; - newNail.transform.localPosition = new Vector3((float)nailX, 0f, 0f); + // var nailX = (beat - startBeat) * -nailDistance; + // newNail.transform.localPosition = new Vector3((float)nailX, 0f, 0f); newNail.Init(); newNail.gameObject.SetActive(true); } @@ -368,9 +466,11 @@ namespace HeavenStudio.Games var newNail = Instantiate(baseLongNail, nailHolder).GetComponent(); newNail.targetBeat = beat; + newNail.targetX = nailHolder.position.x; + newNail.metresPerSecond = scrollMetresPerBeat; - var nailX = (beat - startBeat + 0.5f) * -nailDistance / 2f; - newNail.transform.localPosition = new Vector3((float)nailX, 0f, 0f); + // var nailX = (beat - startBeat) * -nailDistance; + // newNail.transform.localPosition = new Vector3((float)nailX, 0f, 0f); newNail.Init(); newNail.gameObject.SetActive(true); } @@ -380,38 +480,13 @@ namespace HeavenStudio.Games newSweet.targetBeat = beat; newSweet.sweetType = sweetType; + newSweet.targetX = nailHolder.position.x; + newSweet.metresPerSecond = scrollMetresPerBeat; - var sweetX = (beat - startBeat) * -nailDistance / 2f; - newSweet.transform.localPosition = new Vector3((float)sweetX, 0f, 0f); + // var sweetX = (beat - startBeat) * -nailDistance; + // newSweet.transform.localPosition = new Vector3((float)sweetX, 0f, 0f); newSweet.gameObject.SetActive(true); newSweet.Init(); } - - bool IsInRange(List list, double num) - { - foreach (double item in list) - { - if (num >= item && num <= item + .5f) - { - return true; - } - } - return false; - } - - - // MultiSound.Play may not work in OnPlay (OnGameSwitch?), so I play the audio using an alternative method. - List sounds = new List(){}; - bool isPlayed = false; - public void PlaySound() - { - if (isPlayed) return; - if (sounds.Count > 0) { - MultiSound.Play(sounds.ToArray()); - isPlayed = true; - sounds = null; - } - } - } } \ No newline at end of file diff --git a/Assets/Scripts/Games/NailCarpenter/Sweet.cs b/Assets/Scripts/Games/NailCarpenter/Sweet.cs index 53e273e86..04764ce82 100644 --- a/Assets/Scripts/Games/NailCarpenter/Sweet.cs +++ b/Assets/Scripts/Games/NailCarpenter/Sweet.cs @@ -11,17 +11,20 @@ namespace HeavenStudio.Games.Scripts_NailCarpenter public class Sweet : MonoBehaviour { public double targetBeat; + public float targetX; + public float metresPerSecond; public sweetsType sweetType; public Animator sweetAnim; // public SpriteRenderer sweetSprite; - + public enum sweetsType { - Pudding=0, - CherryPudding=1, - ShortCake=2, - Cherry=3, - LayerCake=4, + None = -1, + Pudding = 0, + CherryPudding = 1, + ShortCake = 2, + Cherry = 3, + LayerCake = 4, }; private NailCarpenter game; @@ -31,12 +34,13 @@ namespace HeavenStudio.Games.Scripts_NailCarpenter game = NailCarpenter.instance; AwakeAnim(); - game.ScheduleUserInput(targetBeat, 0, NailCarpenter.InputAction_RegPress, HammmerJust, Empty, Empty); - game.ScheduleUserInput(targetBeat, 0, NailCarpenter.InputAction_AltFinish, HammmerJust, Empty, Empty); + game.ScheduleUserInput(targetBeat, 0, NailCarpenter.InputAction_SweetsHit, HammmerJust, null, null); + Update(); } + private void AwakeAnim() { - switch(sweetType) + switch (sweetType) { case sweetsType.Pudding: sweetAnim.Play("puddingIdle", -1, 0); @@ -55,9 +59,10 @@ namespace HeavenStudio.Games.Scripts_NailCarpenter break; } } + private void BreakAnim() { - switch(sweetType) + switch (sweetType) { case sweetsType.Pudding: sweetAnim.DoScaledAnimationAsync("puddingBreak", 0.25f); @@ -81,13 +86,9 @@ namespace HeavenStudio.Games.Scripts_NailCarpenter { game.ScoreMiss(); BreakAnim(); - game.Carpenter.DoScaledAnimationAsync("carpenterHit", 0.25f); - SoundByte.PlayOneShot("miss"); game.EyeAnim.DoScaledAnimationAsync("eyeBlink", 0.25f); } - private void Empty(PlayerActionEvent caller) { } - private void Update() { var cond = Conductor.instance; @@ -95,7 +96,10 @@ namespace HeavenStudio.Games.Scripts_NailCarpenter if (cond.isPlaying && !cond.isPaused) { double beat = cond.songPositionInBeats; - if (targetBeat != double.MinValue) + Vector3 pos = transform.position; + pos.x = targetX + (float)((beat - targetBeat) * metresPerSecond); + transform.position = pos; + if (targetBeat != double.MinValue) { if (beat >= targetBeat + 9) Destroy(gameObject); }