CNR API Internal Rework (#488)

* Prep stuff

* Tweezers now spawn in

* Started converting tweezers

* I hate <1 beat intervals

* Actually nvm

* fixed a bug

* You can chain intervals now, stack them if you really wanted

* Pass turn checks if crhandlerinstance exists

* Fixed hairs being deleted by onion switch

* Rockers rerewritten

* working dough rerewritten
This commit is contained in:
Rapandrasmus 2023-06-28 06:51:53 +02:00 committed by minenice55
parent 25cae2aff9
commit c7d640db11
10 changed files with 531 additions and 523 deletions

View file

@ -1334,7 +1334,7 @@ GameObject:
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
m_IsActive: 0
--- !u!4 &3942464277001988917
Transform:
m_ObjectHideFlags: 0

View file

@ -10665,9 +10665,9 @@ MonoBehaviour:
doughDudesHolderAnim: {fileID: 9020148957407720643}
gandwAnim: {fileID: 2284918768942303106}
bgObjects:
- {fileID: 8366664867673554297}
- {fileID: 2959293411470963612}
- {fileID: 9159990749478636517}
shipObject: {fileID: 8366664867673554297}
bigMode: 0
bigModePlayer: 0
spaceshipRisen: 0

View file

@ -76,13 +76,6 @@ namespace HeavenStudio.Games
public double intervalStartBeat = -1; // the first beat of the interval
public float intervalLength = -1; // the duration of the interval in beats
public float defaultIntervalLength; // when an event is queued and the interval has not started yet, it will use this as the interval length.
public CallAndResponseHandler(float defaultIntervalLength)
{
this.defaultIntervalLength = defaultIntervalLength;
}
public List<CallAndResponseEvent> queuedEvents = new List<CallAndResponseEvent>();
/// <summary>
@ -95,7 +88,7 @@ namespace HeavenStudio.Games
public float GetIntervalProgressFromBeat(double beat, float lengthOffset = 0)
{
return (float)((beat - intervalStartBeat) / ((intervalStartBeat + intervalLength - lengthOffset) - intervalStartBeat));
return (float)((beat - intervalStartBeat) / Mathf.Max(1, intervalLength - lengthOffset));
}
/// <summary>
@ -113,29 +106,21 @@ namespace HeavenStudio.Games
/// <param name="beat">The interval start beat.</param>
/// <param name="length">The length of the interval.</param>
public void StartInterval(double beat, float length)
{
if (!IntervalIsActive())
{
if (queuedEvents.Count > 0) queuedEvents.Clear();
}
intervalStartBeat = beat;
intervalLength = length;
defaultIntervalLength = length;
}
/// <summary>
/// Adds an event to the queued events list.
/// </summary>
/// <param name="beat">The current beat.</param>
/// <param name="length">The length of the event.</param>>
/// <param name="tag">The tag of the event.</param>
/// <param name="crParams">Extra properties to add to the event.</param>
/// <param name="ignoreInterval">If true, this function will not start a new interval if the interval isn't active.</param>
/// <param name="overrideInterval">If true, overrides the current interval.</param>
public void AddEvent(double beat, float length = 0, string tag = "", List<CallAndResponseEventParam> crParams = null, bool ignoreInterval = false, bool overrideInterval = false)
public void AddEvent(double beat, float length = 0, string tag = "", List<CallAndResponseEventParam> crParams = null)
{
if ((!IntervalIsActive() && !ignoreInterval) || overrideInterval)
{
StartInterval(beat, defaultIntervalLength);
}
CallAndResponseEvent addedEvent = new CallAndResponseEvent(beat, beat - intervalStartBeat, tag, length);
CallAndResponseEvent addedEvent = new(beat, beat - intervalStartBeat, tag, length);
if (crParams != null && crParams.Count > 0)
{
foreach (var param in crParams)
@ -163,7 +148,7 @@ namespace HeavenStudio.Games
/// <summary>
/// Check if an event exists at relativeBeat.
/// </summary>
/// <param name="beat">The beat to check.</param>
/// <param name="relativeBeat">The relativeBeat to check.</param>
public bool EventExistsAtRelativetBeat(double relativeBeat)
{
if (queuedEvents.Count == 0)

View file

@ -7,22 +7,17 @@ namespace HeavenStudio.Games.Scripts_RhythmTweezers
{
public class Hair : MonoBehaviour
{
public double createBeat;
[NonSerialized] public double createBeat;
public GameObject hairSprite;
public GameObject stubbleSprite;
public GameObject missedSprite;
private RhythmTweezers game;
private Tweezers tweezers;
private bool plucked;
private void Awake()
public void StartInput(double beat, double length, Tweezers tweezer)
{
game = RhythmTweezers.instance;
tweezers = game.Tweezers;
}
public void StartInput(double beat, double length)
{
tweezers = tweezer;
game.ScheduleInput(beat, length, InputType.STANDARD_DOWN | InputType.DIRECTION_DOWN, Just, Miss, Out);
}
@ -30,14 +25,12 @@ namespace HeavenStudio.Games.Scripts_RhythmTweezers
{
tweezers.Pluck(true, this);
tweezers.hitOnFrame++;
plucked = true;
}
public void NearMiss()
{
tweezers.Pluck(false, this);
tweezers.hitOnFrame++;
plucked = true;
}
private void Just(PlayerActionEvent caller, float state)

View file

@ -26,15 +26,11 @@ namespace HeavenStudio.Games.Scripts_RhythmTweezers
PlayerActionEvent endEvent;
private void Awake()
public void StartInput(double beat, double length, Tweezers tweezer)
{
game = RhythmTweezers.instance;
anim = GetComponent<Animator>();
tweezers = game.Tweezers;
}
public void StartInput(double beat, double length)
{
tweezers = tweezer;
inputBeat = beat + length;
game.ScheduleInput(beat, length, InputType.STANDARD_DOWN | InputType.DIRECTION_DOWN, StartJust, StartMiss, Out);
}

View file

@ -17,22 +17,20 @@ namespace HeavenStudio.Games.Loaders
{
new GameAction("start interval", "Start Interval")
{
function = delegate { RhythmTweezers.instance.SetIntervalStart(eventCaller.currentEntity.beat, eventCaller.currentEntity.length); },
preFunction = delegate { RhythmTweezers.PreInterval(eventCaller.currentEntity.beat, eventCaller.currentEntity.length, eventCaller.currentEntity["auto"]); },
defaultLength = 4f,
resizable = true,
priority = 1,
inactiveFunction = delegate { RhythmTweezers.InactiveInterval(eventCaller.currentEntity.beat, eventCaller.currentEntity.length); }
parameters = new List<Param>()
{
new Param("auto", true, "Auto Pass Turn", "Will the turn automatically be passed at the end of this event?")
}
},
new GameAction("short hair", "Short Hair")
{
inactiveFunction = delegate { RhythmTweezers.SpawnHairInactive(eventCaller.currentEntity.beat); },
function = delegate { RhythmTweezers.instance.SpawnHair(eventCaller.currentEntity.beat); },
defaultLength = 0.5f
},
new GameAction("long hair", "Curly Hair")
{
inactiveFunction = delegate { RhythmTweezers.SpawnLongHairInactive(eventCaller.currentEntity.beat); },
function = delegate { RhythmTweezers.instance.SpawnLongHair(eventCaller.currentEntity.beat); },
defaultLength = 0.5f
},
new GameAction("passTurn", "Pass Turn")
@ -131,6 +129,7 @@ namespace HeavenStudio.Games.Loaders
namespace HeavenStudio.Games
{
using Jukebox;
using Scripts_RhythmTweezers;
public class RhythmTweezers : Minigame
@ -162,6 +161,7 @@ namespace HeavenStudio.Games
public Animator VegetableAnimator;
public SpriteRenderer bg;
public Tweezers Tweezers;
private Tweezers currentTweezers;
public GameObject hairBase;
public GameObject longHairBase;
public GameObject pluckedHairBase;
@ -169,7 +169,6 @@ namespace HeavenStudio.Games
public GameObject HairsHolder;
public GameObject DroppedHairsHolder;
[NonSerialized] public int hairsLeft = 0;
[Header("Variables")]
private double passTurnBeat;
@ -182,8 +181,6 @@ namespace HeavenStudio.Games
public Sprite onionSprite;
public Sprite potatoSprite;
[NonSerialized] public int eyeSize = 0;
Tween transitionTween;
bool transitioning = false;
Tween bgColorTween;
@ -225,15 +222,18 @@ namespace HeavenStudio.Games
private List<LongHair> spawnedLongs = new List<LongHair>();
private static List<double> passedTurns = new();
private struct QueuedInterval
{
public double beat;
public float interval;
public bool autoPassTurn;
}
private static List<QueuedInterval> queuedIntervals = new List<QueuedInterval>();
private void Awake()
{
instance = this;
if (crHandlerInstance == null)
{
crHandlerInstance = new CallAndResponseHandler(4);
}
if (crHandlerInstance.queuedEvents.Count > 0)
if (crHandlerInstance != null && crHandlerInstance.queuedEvents.Count > 0)
{
foreach (var crEvent in crHandlerInstance.queuedEvents)
{
@ -261,9 +261,14 @@ namespace HeavenStudio.Games
}
}
public override void OnPlay(double beat)
{
crHandlerInstance = null;
}
private void OnDestroy()
{
if (crHandlerInstance != null && !Conductor.instance.isPlaying)
if (!Conductor.instance.isPlaying)
{
crHandlerInstance = null;
}
@ -273,24 +278,30 @@ namespace HeavenStudio.Games
}
}
public static void SpawnHairInactive(double beat)
private void SpawnHairInactive(double beat)
{
if (crHandlerInstance == null)
{
crHandlerInstance = new CallAndResponseHandler(4);
}
if (crHandlerInstance.queuedEvents.Count > 0 && crHandlerInstance.queuedEvents.Find(x => x.beat == beat || (beat >= x.beat && beat <= x.beat + x.length)) != null) return;
crHandlerInstance.AddEvent(beat, 0, "Hair");
Hair hair = Instantiate(hairBase, HairsHolder.transform).GetComponent<Hair>();
spawnedHairs.Add(hair);
hair.gameObject.SetActive(true);
hair.GetComponent<Animator>().Play("SmallAppear", 0, 1);
float rot = -58f + 116 * crHandlerInstance.GetIntervalProgressFromBeat(beat, 1);
hair.transform.eulerAngles = new Vector3(0, 0, rot);
hair.createBeat = beat;
}
public static void SpawnLongHairInactive(double beat)
private void SpawnLongHairInactive(double beat)
{
if (crHandlerInstance == null)
{
crHandlerInstance = new CallAndResponseHandler(4);
}
if (crHandlerInstance.queuedEvents.Count > 0 && crHandlerInstance.queuedEvents.Find(x => x.beat == beat || (beat >= x.beat && beat <= x.beat + x.length)) != null) return;
crHandlerInstance.AddEvent(beat, 0.5f, "Long");
LongHair hair = Instantiate(longHairBase, HairsHolder.transform).GetComponent<LongHair>();
spawnedLongs.Add(hair);
hair.gameObject.SetActive(true);
hair.GetComponent<Animator>().Play("LongAppear", 0, 1);
float rot = -58f + 116 * crHandlerInstance.GetIntervalProgressFromBeat(beat, 1);
hair.transform.eulerAngles = new Vector3(0, 0, rot);
hair.createBeat = beat;
}
public void SpawnHair(double beat)
@ -302,10 +313,18 @@ namespace HeavenStudio.Games
crHandlerInstance.AddEvent(beat, 0, "Hair");
SoundByte.PlayOneShotGame("rhythmTweezers/shortAppear", beat);
Hair hair = Instantiate(hairBase, HairsHolder.transform).GetComponent<Hair>();
Hair hair = Instantiate(hairBase, transform).GetComponent<Hair>();
spawnedHairs.Add(hair);
BeatAction.New(instance.gameObject, new List<BeatAction.Action>()
{
new BeatAction.Action(beat, delegate
{
hair.gameObject.SetActive(true);
hair.GetComponent<Animator>().Play("SmallAppear", 0, 0);
hair.transform.SetParent(HairsHolder.transform, false);
})
});
float rot = -58f + 116 * crHandlerInstance.GetIntervalProgressFromBeat(beat, 1);
hair.transform.eulerAngles = new Vector3(0, 0, rot);
@ -320,88 +339,136 @@ namespace HeavenStudio.Games
crHandlerInstance.AddEvent(beat, 0.5f, "Long");
SoundByte.PlayOneShotGame("rhythmTweezers/longAppear", beat);
LongHair hair = Instantiate(longHairBase, HairsHolder.transform).GetComponent<LongHair>();
LongHair hair = Instantiate(longHairBase, transform).GetComponent<LongHair>();
spawnedLongs.Add(hair);
BeatAction.New(instance.gameObject, new List<BeatAction.Action>()
{
new BeatAction.Action(beat, delegate
{
hair.gameObject.SetActive(true);
hair.GetComponent<Animator>().Play("LongAppear", 0, 0);
hair.transform.SetParent(HairsHolder.transform, false);
})
});
float rot = -58f + 116 * crHandlerInstance.GetIntervalProgressFromBeat(beat, 1);
hair.transform.eulerAngles = new Vector3(0, 0, rot);
hair.createBeat = beat;
}
public void SetIntervalStart(double beat, float interval = 4f)
private void SetIntervalStart(double beat, double gameSwitchBeat, float interval = 4f, bool autoPassTurn = true)
{
StopTransitionIfActive();
hairsLeft = 0;
eyeSize = 0;
CallAndResponseHandler newHandler = new();
crHandlerInstance = newHandler;
crHandlerInstance.StartInterval(beat, interval);
List<RiqEntity> relevantHairEvents = GetAllHairsInBetweenBeat(beat, beat + interval);
foreach (var hairEvent in relevantHairEvents)
{
if (hairEvent.beat >= gameSwitchBeat)
{
if (hairEvent.datamodel == "rhythmTweezers/short hair")
{
SpawnHair(hairEvent.beat);
}
else
{
SpawnLongHair(hairEvent.beat);
}
}
else
{
if (hairEvent.datamodel == "rhythmTweezers/short hair")
{
SpawnHairInactive(hairEvent.beat);
}
else
{
SpawnLongHairInactive(hairEvent.beat);
}
}
}
if (autoPassTurn)
{
PassTurn(beat + interval, interval, newHandler);
}
}
public static void InactiveInterval(double beat, float interval)
public static void PreInterval(double beat, float interval = 4f, bool autoPassTurn = true)
{
if (crHandlerInstance == null)
if (GameManager.instance.currentGame == "rhythmTweezers")
{
crHandlerInstance = new CallAndResponseHandler(4);
instance.SetIntervalStart(beat, beat, interval, autoPassTurn);
}
crHandlerInstance.StartInterval(beat, interval);
}
public void PassTurn(double beat)
else
{
if (crHandlerInstance.queuedEvents.Count > 0)
queuedIntervals.Add(new QueuedInterval()
{
BeatAction.New(instance.gameObject, new List<BeatAction.Action>()
{
new BeatAction.Action(beat - 1, delegate
{
hairsLeft = crHandlerInstance.queuedEvents.Count;
foreach (var crEvent in crHandlerInstance.queuedEvents)
{
if (crEvent.tag == "Hair")
{
Hair hairToInput = spawnedHairs.Find(x => x.createBeat == crEvent.beat);
hairToInput.StartInput(beat, crEvent.relativeBeat);
}
else if (crEvent.tag == "Long")
{
LongHair hairToInput = spawnedLongs.Find(x => x.createBeat == crEvent.beat);
hairToInput.StartInput(beat, crEvent.relativeBeat);
}
}
crHandlerInstance.queuedEvents.Clear();
}),
new BeatAction.Action(beat, delegate
{
if (crHandlerInstance.queuedEvents.Count > 0)
{
hairsLeft += crHandlerInstance.queuedEvents.Count;
foreach (var crEvent in crHandlerInstance.queuedEvents)
{
if (crEvent.tag == "Hair")
{
Hair hairToInput = spawnedHairs.Find(x => x.createBeat == crEvent.beat);
hairToInput.StartInput(beat, crEvent.relativeBeat);
}
else if (crEvent.tag == "Long")
{
LongHair hairToInput = spawnedLongs.Find(x => x.createBeat == crEvent.beat);
hairToInput.StartInput(beat, crEvent.relativeBeat);
}
}
crHandlerInstance.queuedEvents.Clear();
}
})
beat = beat,
interval = interval,
autoPassTurn = autoPassTurn
});
}
}
private static List<RiqEntity> GetAllHairsInBetweenBeat(double beat, double endBeat)
{
List<RiqEntity> hairEvents = EventCaller.GetAllInGameManagerList("rhythmTweezers", new string[] { "short hair", "long hair"});
List<RiqEntity> tempEvents = new();
foreach (var entity in hairEvents)
{
if (entity.beat >= beat && entity.beat < endBeat)
{
tempEvents.Add(entity);
}
}
return tempEvents;
}
private void PassTurnStandalone(double beat)
{
if (crHandlerInstance != null) PassTurn(beat, crHandlerInstance.intervalLength, crHandlerInstance);
}
private void PassTurn(double beat, double length, CallAndResponseHandler crHandler)
{
Tweezers spawnedTweezers = Instantiate(Tweezers, transform);
spawnedTweezers.gameObject.SetActive(true);
spawnedTweezers.Init(beat, beat + length);
BeatAction.New(instance.gameObject, new List<BeatAction.Action>()
{
new BeatAction.Action(beat - 0.25, delegate
{
if (crHandler.queuedEvents.Count > 0)
{
currentTweezers = spawnedTweezers;
spawnedTweezers.hairsLeft = crHandler.queuedEvents.Count;
foreach (var crEvent in crHandler.queuedEvents)
{
if (crEvent.tag == "Hair")
{
Hair hairToInput = spawnedHairs.Find(x => x.createBeat == crEvent.beat);
hairToInput.StartInput(beat, crEvent.relativeBeat, spawnedTweezers);
}
else if (crEvent.tag == "Long")
{
LongHair hairToInput = spawnedLongs.Find(x => x.createBeat == crEvent.beat);
hairToInput.StartInput(beat, crEvent.relativeBeat, spawnedTweezers);
}
}
crHandler.queuedEvents.Clear();
}
}),
});
}
public static void PrePassTurn(double beat)
{
if (GameManager.instance.currentGame == "rhythmTweezers")
{
instance.SetPassTurnValues(beat);
instance.PassTurn(beat);
instance.PassTurnStandalone(beat);
}
else
{
@ -409,13 +476,6 @@ namespace HeavenStudio.Games
}
}
private void SetPassTurnValues(double startBeat)
{
if (crHandlerInstance.intervalLength <= 0) return;
passTurnBeat = startBeat - 1;
passTurnEndBeat = startBeat + crHandlerInstance.intervalLength;
}
const float vegDupeOffset = 16.7f;
public void NextVegetable(double beat, int type, Color onionColor, Color potatoColor)
{
@ -514,8 +574,7 @@ namespace HeavenStudio.Games
{
foreach (var turn in passedTurns)
{
SetPassTurnValues(turn);
PassTurn(turn);
PassTurnStandalone(turn);
}
passedTurns.Clear();
}
@ -530,28 +589,25 @@ namespace HeavenStudio.Games
}
}
private void LateUpdate()
public override void OnGameSwitch(double beat)
{
// Set tweezer angle.
var tweezerAngle = -180f;
var tweezerTime = Conductor.instance.songPositionInBeats;
var unclampedAngle = -58f + 116 * Mathp.Normalize(tweezerTime, (float)passTurnBeat + 1f, (float)passTurnEndBeat - 1f);
tweezerAngle = Mathf.Clamp(unclampedAngle, -180f, 180f);
Tweezers.transform.eulerAngles = new Vector3(0, 0, tweezerAngle);
// Set tweezer to follow vegetable.
var currentTweezerPos = Tweezers.transform.localPosition;
var vegetablePos = Vegetable.transform.localPosition;
var vegetableHolderPos = VegetableHolder.transform.localPosition;
Tweezers.transform.localPosition = new Vector3(vegetableHolderPos.x, vegetablePos.y + 1f, currentTweezerPos.z);
if (Conductor.instance.isPlaying && !Conductor.instance.isPaused)
{
if (queuedIntervals.Count > 0)
{
foreach (var interval in queuedIntervals)
{
SetIntervalStart(interval.beat, beat, interval.interval, interval.autoPassTurn);
}
queuedIntervals.Clear();
}
}
}
private void ResetVegetable()
{
// If the tweezers happen to be holding a hair, drop it immediately so it can be destroyed below.
Tweezers.DropHeldHair();
currentTweezers?.DropHeldHair();
foreach (Transform t in HairsHolder.transform)
{
@ -564,8 +620,6 @@ namespace HeavenStudio.Games
}
VegetableAnimator.Play("Idle", 0, 0);
eyeSize = 0;
}
private void StopTransitionIfActive()

View file

@ -4,6 +4,7 @@ using UnityEngine;
using System;
using HeavenStudio.Util;
using Starpelly;
namespace HeavenStudio.Games.Scripts_RhythmTweezers
{
@ -17,6 +18,10 @@ namespace HeavenStudio.Games.Scripts_RhythmTweezers
private bool holdingHair;
public SpriteRenderer heldHairSprite;
public Transform tweezerSpriteTrans;
private double passTurnBeat = -1;
private double passTurnEndBeat = -1;
[NonSerialized] public int hairsLeft;
private int eyeSize = 0;
private void Awake()
{
@ -26,6 +31,37 @@ namespace HeavenStudio.Games.Scripts_RhythmTweezers
game = RhythmTweezers.instance;
}
public void Init(double beat, double endBeat)
{
passTurnBeat = beat;
passTurnEndBeat = endBeat;
Update();
}
private void Update()
{
if (passTurnBeat != -1)
{
// Set tweezer angle.
float tweezerTime = Conductor.instance.GetPositionFromBeat(passTurnBeat, Math.Max(passTurnEndBeat - 1f - passTurnBeat, 1));
var unclampedAngle = -58f + (116 * tweezerTime);
var tweezerAngle = Mathf.Clamp(unclampedAngle, -180f, 180f);
transform.eulerAngles = new Vector3(0, 0, tweezerAngle);
// Set tweezer to follow vegetable.
var currentTweezerPos = transform.localPosition;
var vegetablePos = game.Vegetable.transform.localPosition;
var vegetableHolderPos = game.VegetableHolder.transform.localPosition;
transform.localPosition = new Vector3(vegetableHolderPos.x, vegetablePos.y + 1f, currentTweezerPos.z);
if (tweezerAngle == 180)
{
Destroy(gameObject);
}
}
}
private void LateUpdate()
{
if (PlayerInput.Pressed(true))
@ -51,13 +87,13 @@ namespace HeavenStudio.Games.Scripts_RhythmTweezers
hair.hairSprite.SetActive(false);
hair.stubbleSprite.SetActive(true);
game.hairsLeft--;
game.eyeSize = Mathf.Clamp(game.eyeSize + 1, 0, 10);
hairsLeft--;
eyeSize = Mathf.Clamp(eyeSize + 1, 0, 10);
if (game.hairsLeft <= 0)
if (hairsLeft <= 0)
vegetableAnim.Play("HopFinal", 0, 0);
else
vegetableAnim.Play("Hop" + game.eyeSize.ToString(), 0, 0);
vegetableAnim.Play("Hop" + eyeSize.ToString(), 0, 0);
anim.Play("Tweezers_Pluck_Success", 0, 0);
}
@ -91,13 +127,13 @@ namespace HeavenStudio.Games.Scripts_RhythmTweezers
// Making transparent instead of disabling because animators are silly.
hair.loop.GetComponent<SpriteRenderer>().color = Color.clear;
game.hairsLeft--;
game.eyeSize = Mathf.Clamp(game.eyeSize + 1, 0, 10);
hairsLeft--;
eyeSize = Mathf.Clamp(eyeSize + 1, 0, 10);
if (game.hairsLeft <= 0)
if (hairsLeft <= 0)
vegetableAnim.Play("HopFinal", 0, 0);
else
vegetableAnim.Play("Hop" + game.eyeSize.ToString(), 0, 0);
vegetableAnim.Play("Hop" + eyeSize.ToString(), 0, 0);
anim.Play("Tweezers_Pluck_Success", 0, 0);
}

View file

@ -17,35 +17,18 @@ namespace HeavenStudio.Games.Loaders
{
new GameAction("intervalStart", "Start Interval")
{
function = delegate { var e = eventCaller.currentEntity; Rockers.instance.StartInterval(e.beat, e.length); },
defaultLength = 8f,
resizable = true,
preFunction = delegate { Rockers.PreMoveCamera(eventCaller.currentEntity.beat, eventCaller.currentEntity["moveCamera"]); },
preFunction = delegate { var e = eventCaller.currentEntity; Rockers.PreInterval(e.beat, e.length, e["auto"], e["moveCamera"], e["movePass"]); },
parameters = new List<Param>()
{
new Param("moveCamera", true, "Move Camera", "Should the camera move?")
new Param("moveCamera", true, "Move Camera", "Should the camera move?"),
new Param("movePass", true, "Move Camera (Pass Turn)", "Should the camera move at the auto pass turn?"),
new Param("auto", true, "Auto Pass Turn")
},
inactiveFunction = delegate { var e = eventCaller.currentEntity; Rockers.InactiveInterval(e.beat, e.length); }
},
new GameAction("riff", "Riff")
{
function = delegate { var e = eventCaller.currentEntity; Rockers.instance.Riff(e.beat, e.length, new int[6]
{
e["1JJ"],
e["2JJ"],
e["3JJ"],
e["4JJ"],
e["5JJ"],
e["6JJ"],
}, e["gcJJ"], new int[6]
{
e["1S"],
e["2S"],
e["3S"],
e["4S"],
e["5S"],
e["6S"],
}, e["gcS"], e["sampleJJ"], e["pitchSampleJJ"], e["sampleS"], e["pitchSampleS"], !e["respond"]); },
defaultLength = 1f,
resizable = true,
parameters = new List<Param>()
@ -70,19 +53,9 @@ namespace HeavenStudio.Games.Loaders
new Param("pitchSampleS", new EntityTypes.Integer(-24, 24, 0), "Sample Semtiones (Soshi)", "Pitch up the sample by X amount of semitones?"),
new Param("gcS", false, "Glee Club Guitar (Soshi)", "Will Soshi use the same guitar as in the glee club lessons?")
},
inactiveFunction = delegate { var e = eventCaller.currentEntity; Rockers.InactiveRiff(e.beat, e.length, new int[6]
{
e["1S"],
e["2S"],
e["3S"],
e["4S"],
e["5S"],
e["6S"],
}, e["gcS"], e["sampleS"], e["pitchSampleS"]); }
},
new GameAction("bend", "Bend")
{
function = delegate { var e = eventCaller.currentEntity; Rockers.instance.Bend(e.beat, e.length, e["1JJ"], e["1S"], !e["respond"]); },
defaultLength = 1f,
resizable = true,
parameters = new List<Param>()
@ -91,7 +64,6 @@ namespace HeavenStudio.Games.Loaders
new Param("1JJ", new EntityTypes.Integer(-24, 24, 1), "Pitch Bend (JJ)", "How many semitones up is the current riff gonna be pitchbended?"),
new Param("1S", new EntityTypes.Integer(-24, 24, 1), "Pitch Bend (Soshi)", "How many semitones up is the current riff gonna be pitchbended?"),
},
inactiveFunction = delegate { var e = eventCaller.currentEntity; Rockers.InactiveBend(e.beat, e.length, e["1S"]); }
},
new GameAction("prepare", "Prepare")
{
@ -320,9 +292,6 @@ namespace HeavenStudio.Games.Loaders
namespace HeavenStudio.Games
{
using Scripts_Rockers;
using Starpelly;
using System;
using UnityEngine.UIElements;
public class Rockers : Minigame
{
@ -402,24 +371,30 @@ namespace HeavenStudio.Games
private double cameraMoveBeat = -1;
private double endBeat = double.MaxValue;
private static List<double> queuedCameraEvents = new();
private static List<double> queuedPreInterval = new();
private List<RiqEntity> riffEvents = new List<RiqEntity>();
private static List<double> riffUsedBeats = new();
private List<RiqEntity> bendEvents = new List<RiqEntity>();
private static List<double> bendUsedBeats = new();
private List<double> prepareBeatsJJ = new();
private struct QueuedInterval
{
public double beat;
public float length;
public bool moveCamera;
public bool moveCameraPass;
public bool autoPassTurn;
}
private static List<QueuedInterval> queuedIntervals = new();
private void Awake()
{
instance = this;
if (crHandlerInstance == null)
{
crHandlerInstance = new CallAndResponseHandler(8);
crHandlerInstance = new CallAndResponseHandler();
}
var tempEvents = EventCaller.GetAllInGameManagerList("rockers", new string[] { "prepare" });
foreach (var tempEvent in tempEvents)
@ -480,6 +455,21 @@ namespace HeavenStudio.Games
}
}
private static List<RiqEntity> GrabAllInputsBetween(double beat, double endBeat)
{
List<RiqEntity> hairEvents = EventCaller.GetAllInGameManagerList("rockers", new string[] { "riff", "bend" });
List<RiqEntity> tempEvents = new();
foreach (var entity in hairEvents)
{
if (entity.beat >= beat && entity.beat < endBeat)
{
tempEvents.Add(entity);
}
}
return tempEvents;
}
private List<RiqEntity> GrabAllTogetherEvents(double beat)
{
var tempEvents = EventCaller.GetAllInGameManagerList("rockers", new string[] { "riffTogether", "riffTogetherEnd" });
@ -546,22 +536,32 @@ namespace HeavenStudio.Games
}
}
private void OnDestroy()
{
if (!Conductor.instance.isPlaying)
public override void OnPlay(double beat)
{
crHandlerInstance = null;
if (riffUsedBeats.Count > 0) riffUsedBeats.Clear();
if (bendUsedBeats.Count > 0) bendUsedBeats.Clear();
}
private void OnDestroy()
{
if (queuedCameraEvents.Count > 0) queuedCameraEvents.Clear();
if (queuedPreInterval.Count > 0) queuedPreInterval.Clear();
foreach (var evt in scheduledInputs)
{
evt.Disable();
}
}
public override void OnGameSwitch(double beat)
{
if (queuedIntervals.Count > 0)
{
foreach (var interval in queuedIntervals)
{
StartInterval(interval.beat, interval.length, beat, interval.autoPassTurn, interval.moveCameraPass);
}
queuedIntervals.Clear();
}
}
private void Update()
{
var cond = Conductor.instance;
@ -593,20 +593,12 @@ namespace HeavenStudio.Games
}
queuedCameraEvents.Clear();
}
if (queuedPreInterval.Count > 0)
{
foreach (var interval in queuedPreInterval)
{
PreInterval(interval);
}
queuedPreInterval.Clear();
}
if (passedTurns.Count > 0)
{
foreach (var turn in passedTurns)
{
PassTurn(turn.beat, turn.moveCamera);
StandalonePassTurn(turn.beat, turn.moveCamera);
}
passedTurns.Clear();
}
@ -621,12 +613,6 @@ namespace HeavenStudio.Games
GameCamera.additionalPosition = new Vector3(newX, 0, 0);
}
}
if (!Conductor.instance.isPlaying)
{
crHandlerInstance = null;
if (riffUsedBeats.Count > 0) riffUsedBeats.Clear();
if (bendUsedBeats.Count > 0) bendUsedBeats.Clear();
}
}
public void DefaultLastOne(double beat, int[] JJSamples, int[] JJPitches, int[] SoshiSamples, int[] SoshiPitches, bool moveCamera)
@ -827,15 +813,22 @@ namespace HeavenStudio.Games
BeatAction.New(instance.gameObject, actions);
}
public static void PreMoveCamera(double beat, bool moveCamera)
public static void PreInterval(double beat, float length, bool autoPassTurn, bool moveCamera, bool movePass)
{
if (GameManager.instance.currentGame == "rockers")
{
if (moveCamera) instance.MoveCamera(beat - 1);
instance.PreInterval(beat - 1);
instance.StartInterval(beat, length, beat, autoPassTurn, movePass);
}
if (moveCamera) queuedCameraEvents.Add(beat - 1);
queuedPreInterval.Add(beat - 1);
queuedIntervals.Add(new QueuedInterval()
{
beat = beat,
length = length,
autoPassTurn = autoPassTurn,
moveCamera = moveCamera,
moveCameraPass = movePass
});
}
private void MoveCamera(double beat)
@ -846,91 +839,104 @@ namespace HeavenStudio.Games
}
private void PreInterval(double beat)
public void StartInterval(double beat, float length, double gameSwitchBeat, bool autoPassTurn, bool moveCamera)
{
CallAndResponseHandler newHandler = new();
crHandlerInstance = newHandler;
crHandlerInstance.StartInterval(beat, length);
List<RiqEntity> relevantInputs = GrabAllInputsBetween(beat, beat + length);
List<double> riffUsedBeats = new List<double>();
List<double> bendUsedBeats = new();
foreach (var input in relevantInputs)
{
if (input.datamodel == "rockers/riff")
{
RiqEntity foundEvent = riffEvents.Find(x => x.beat == input.beat);
if ((foundEvent == null || (riffUsedBeats.Count > 0 && riffUsedBeats.Contains((float)foundEvent.beat))) && riffEvents.Count > 1) continue;
riffUsedBeats.Add(input.beat);
if (input["respond"])
{
crHandlerInstance.AddEvent(input.beat, input.length, "riff", new List<CallAndResponseHandler.CallAndResponseEventParam>()
{
new CallAndResponseHandler.CallAndResponseEventParam("gleeClub", input["gcS"]),
new CallAndResponseHandler.CallAndResponseEventParam("1", input["1S"]),
new CallAndResponseHandler.CallAndResponseEventParam("2", input["2S"]),
new CallAndResponseHandler.CallAndResponseEventParam("3", input["3S"]),
new CallAndResponseHandler.CallAndResponseEventParam("4", input["4S"]),
new CallAndResponseHandler.CallAndResponseEventParam("5", input["5S"]),
new CallAndResponseHandler.CallAndResponseEventParam("6", input["6S"]),
new CallAndResponseHandler.CallAndResponseEventParam("sample", input["sampleS"]),
new CallAndResponseHandler.CallAndResponseEventParam("sampleTones", input["pitchSampleS"])
});
}
if (input.beat >= gameSwitchBeat)
{
BeatAction.New(instance.gameObject, new List<BeatAction.Action>()
{
new BeatAction.Action(input.beat, delegate { Riff(input.beat, input.length, new int[]
{
input["1JJ"],
input["2JJ"],
input["3JJ"],
input["4JJ"],
input["5JJ"],
input["6JJ"],
}, input["gcJJ"], input["sampleJJ"], input["pitchSampleJJ"], !input["respond"]);
})
});
}
}
else
{
if (riffEvents.Count == 0) continue;
RiqEntity foundEvent = bendEvents.Find(x => x.beat == beat);
if ((foundEvent == null || (bendUsedBeats.Count > 0 && bendUsedBeats.Contains((float)foundEvent.beat))) && bendEvents.Count > 1) continue;
RiqEntity riffEventToCheck = riffEvents.Find(x => beat >= x.beat && beat < x.beat + x.length);
if (riffEventToCheck == null) continue;
bendUsedBeats.Add(beat);
if (input["respond"])
{
crHandlerInstance.AddEvent(input.beat, input.length, "bend", new List<CallAndResponseHandler.CallAndResponseEventParam>()
{
new CallAndResponseHandler.CallAndResponseEventParam("Pitch", input["1S"]),
});
}
if (input.beat >= gameSwitchBeat)
{
BeatAction.New(instance.gameObject, new List<BeatAction.Action>()
{
new BeatAction.Action(input.beat, delegate
{
Bend(input.beat, input.length, input["1JJ"]);
})
});
}
}
}
BeatAction.New(instance.gameObject, new List<BeatAction.Action>()
{
new BeatAction.Action(beat, delegate
{
if (GameManager.instance.autoplay) Soshi.UnHold();
if (JJ.together || Soshi.together)
{
JJ.ReturnBack();
if (prepareBeatsJJ.Count > 0 && prepareBeatsJJ.Contains(beat)) JJ.Mute(false);
Soshi.ReturnBack();
}
})
}),
});
if (autoPassTurn) PassTurn(beat + length, moveCamera, newHandler);
}
public static void InactiveInterval(double beat, float length)
public void Riff(double beat, float length, int[] pitches, bool gleeClubJJ, int sampleJJ, int sampleTonesJJ, bool noRespond)
{
if (crHandlerInstance == null)
{
crHandlerInstance = new CallAndResponseHandler(8);
}
crHandlerInstance.StartInterval(beat, length);
}
public void StartInterval(double beat, float length)
{
crHandlerInstance.StartInterval(beat, length);
if (GameManager.instance.autoplay) Soshi.UnHold();
}
public static void InactiveRiff(double beat, float length, int[] pitchesPlayer, bool gleeClubPlayer, int sampleSoshi, int sampleTonesSoshi)
{
if (crHandlerInstance == null)
{
crHandlerInstance = new CallAndResponseHandler(8);
}
List<RiqEntity> foundRiffEvents = GrabAllRiffEvents();
RiqEntity foundEvent = foundRiffEvents.Find(x => x.beat == beat);
if ((foundEvent == null || (riffUsedBeats.Count > 0 && riffUsedBeats.Contains(foundEvent.beat))) && foundRiffEvents.Count > 1) return;
riffUsedBeats.Add(beat);
crHandlerInstance.AddEvent(beat, length, "riff", new List<CallAndResponseHandler.CallAndResponseEventParam>()
{
new CallAndResponseHandler.CallAndResponseEventParam("gleeClub", gleeClubPlayer),
new CallAndResponseHandler.CallAndResponseEventParam("1", pitchesPlayer[0]),
new CallAndResponseHandler.CallAndResponseEventParam("2", pitchesPlayer[1]),
new CallAndResponseHandler.CallAndResponseEventParam("3", pitchesPlayer[2]),
new CallAndResponseHandler.CallAndResponseEventParam("4", pitchesPlayer[3]),
new CallAndResponseHandler.CallAndResponseEventParam("5", pitchesPlayer[4]),
new CallAndResponseHandler.CallAndResponseEventParam("6", pitchesPlayer[5]),
new CallAndResponseHandler.CallAndResponseEventParam("sample", sampleSoshi),
new CallAndResponseHandler.CallAndResponseEventParam("sampleTones", sampleTonesSoshi)
});
}
public static void InactiveBend(double beat, float length, int pitchSoshi)
{
if (crHandlerInstance == null)
{
crHandlerInstance = new CallAndResponseHandler(8);
}
var bendEventsToCheck = GrabAllBendEvents();
var riffEventsToCheck = GrabAllRiffEvents();
if (riffEventsToCheck.Count == 0) return;
RiqEntity foundEvent = bendEventsToCheck.Find(x => x.beat == beat);
if ((foundEvent == null || (bendUsedBeats.Count > 0 && bendUsedBeats.Contains((float)foundEvent.beat))) && bendEventsToCheck.Count > 1) return;
RiqEntity riffEventToCheck = riffEventsToCheck.Find(x => beat >= x.beat && beat < x.beat + x.length);
if (riffEventToCheck == null) return;
bendUsedBeats.Add(beat);
crHandlerInstance.AddEvent(beat, length, "bend", new List<CallAndResponseHandler.CallAndResponseEventParam>()
{
new CallAndResponseHandler.CallAndResponseEventParam("Pitch", pitchSoshi),
});
}
public void Riff(double beat, float length, int[] pitches, bool gleeClubJJ, int[] pitchesPlayer, bool gleeClubPlayer, int sampleJJ, int sampleTonesJJ, int sampleSoshi, int sampleTonesSoshi, bool noRespond)
{
RiqEntity foundEvent = riffEvents.Find(x => x.beat == beat);
if ((foundEvent == null || (riffUsedBeats.Count > 0 && riffUsedBeats.Contains((float)foundEvent.beat))) && riffEvents.Count > 1) return;
riffUsedBeats.Add(beat);
JJ.StrumStrings(gleeClubJJ, pitches, (PremadeSamples)sampleJJ, sampleTonesJJ, noRespond);
BeatAction.New(instance.gameObject, new List<BeatAction.Action>()
{
new BeatAction.Action(beat + length, delegate { JJ.Mute(); })
});
/*
if (noRespond) return;
crHandlerInstance.AddEvent(beat, length, "riff", new List<CallAndResponseHandler.CallAndResponseEventParam>()
{
@ -944,26 +950,16 @@ namespace HeavenStudio.Games
new CallAndResponseHandler.CallAndResponseEventParam("sample", sampleSoshi),
new CallAndResponseHandler.CallAndResponseEventParam("sampleTones", sampleTonesSoshi)
});
*/
}
public void Bend(double beat, float length, int pitchJJ, int pitchSoshi, bool noRespond)
public void Bend(double beat, float length, int pitchJJ)
{
if (riffEvents.Count == 0) return;
RiqEntity foundEvent = bendEvents.Find(x => x.beat == beat);
if ((foundEvent == null || (bendUsedBeats.Count > 0 && bendUsedBeats.Contains((float)foundEvent.beat))) && bendEvents.Count > 1) return;
RiqEntity riffEventToCheck = riffEvents.Find(x => beat >= x.beat && beat < x.beat + x.length);
if (riffEventToCheck == null) return;
bendUsedBeats.Add(beat);
JJ.BendUp(pitchJJ);
BeatAction.New(instance.gameObject, new List<BeatAction.Action>()
{
new BeatAction.Action(beat + length, delegate { JJ.BendDown(); })
});
if (noRespond) return;
crHandlerInstance.AddEvent(beat, length, "bend", new List<CallAndResponseHandler.CallAndResponseEventParam>()
{
new CallAndResponseHandler.CallAndResponseEventParam("Pitch", pitchSoshi),
});
}
public void Mute(int whoMutes)
@ -994,7 +990,7 @@ namespace HeavenStudio.Games
{
if (GameManager.instance.currentGame == "rockers")
{
instance.PassTurn(beat, moveCamera);
instance.StandalonePassTurn(beat, moveCamera);
}
else
{
@ -1006,7 +1002,12 @@ namespace HeavenStudio.Games
}
}
private void PassTurn(double beat, bool moveCamera)
private void StandalonePassTurn(double beat, bool moveCamera)
{
if (crHandlerInstance != null) PassTurn(beat, moveCamera, crHandlerInstance);
}
private void PassTurn(double beat, bool moveCamera, CallAndResponseHandler handler)
{
if (crHandlerInstance.queuedEvents.Count > 0)
{
@ -1014,59 +1015,40 @@ namespace HeavenStudio.Games
{
new BeatAction.Action(beat - 1, delegate
{
List<CallAndResponseHandler.CallAndResponseEvent> crEvents = crHandlerInstance.queuedEvents;
foreach (var crEvent in crEvents)
{
if (crEvent.tag == "riff")
{
RockersInput riffComp = Instantiate(rockerInputRef, transform);
riffComp.Init(crEvent["gleeClub"], new int[6] { crEvent["1"], crEvent["2"], crEvent["3"], crEvent["4"], crEvent["5"], crEvent["6"] }, beat, crEvent.relativeBeat,
(PremadeSamples)crEvent["sample"], crEvent["sampleTones"]);
ScheduleInput(beat, crEvent.relativeBeat + crEvent.length, InputType.STANDARD_DOWN, JustMute, MuteMiss, Empty);
}
else if (crEvent.tag == "bend")
{
RockerBendInput bendComp = Instantiate(rockerBendInputRef, transform);
bendComp.Init(crEvent["Pitch"], beat, crEvent.relativeBeat);
ScheduleInput(beat, crEvent.relativeBeat + crEvent.length, InputType.DIRECTION_UP, JustUnBend, UnBendMiss, Empty);
}
}
crHandlerInstance.queuedEvents.Clear();
}),
new BeatAction.Action(beat, delegate
{
JJ.UnHold();
if (crHandlerInstance.queuedEvents.Count > 0)
{
List<CallAndResponseHandler.CallAndResponseEvent> crEvents = crHandlerInstance.queuedEvents;
foreach (var crEvent in crEvents)
{
if (crEvent.tag == "riff")
{
RockersInput riffComp = Instantiate(rockerInputRef, transform);
riffComp.Init(crEvent["gleeClub"], new int[6] { crEvent["1"], crEvent["2"], crEvent["3"], crEvent["4"], crEvent["5"], crEvent["6"] }, beat, crEvent.relativeBeat,
(PremadeSamples)crEvent["sample"], crEvent["sampleTones"]);
ScheduleInput(beat, crEvent.relativeBeat + crEvent.length, InputType.STANDARD_DOWN, JustMute, MuteMiss, Empty);
}
else if (crEvent.tag == "bend")
{
RockerBendInput bendComp = Instantiate(rockerBendInputRef, transform);
bendComp.Init(crEvent["Pitch"], beat, crEvent.relativeBeat);
ScheduleInput(beat, crEvent.relativeBeat + crEvent.length, InputType.DIRECTION_UP, JustUnBend, UnBendMiss, Empty);
}
}
crHandlerInstance.queuedEvents.Clear();
}
})
});
if (moveCamera)
{
lastTargetCameraX = GameCamera.additionalPosition.x;
targetCameraX = Soshi.transform.localPosition.x;
cameraMoveBeat = beat - 1;
}
}),
new BeatAction.Action(beat -0.25, delegate
{
List<CallAndResponseHandler.CallAndResponseEvent> crEvents = handler.queuedEvents;
foreach (var crEvent in crEvents)
{
if (crEvent.tag == "riff")
{
RockersInput riffComp = Instantiate(rockerInputRef, transform);
riffComp.Init(crEvent["gleeClub"], new int[6] { crEvent["1"], crEvent["2"], crEvent["3"], crEvent["4"], crEvent["5"], crEvent["6"] }, beat, crEvent.relativeBeat,
(PremadeSamples)crEvent["sample"], crEvent["sampleTones"]);
ScheduleInput(beat, crEvent.relativeBeat + crEvent.length, InputType.STANDARD_DOWN, JustMute, MuteMiss, Empty);
}
else if (crEvent.tag == "bend")
{
RockerBendInput bendComp = Instantiate(rockerBendInputRef, transform);
bendComp.Init(crEvent["Pitch"], beat, crEvent.relativeBeat);
ScheduleInput(beat, crEvent.relativeBeat + crEvent.length, InputType.DIRECTION_UP, JustUnBend, UnBendMiss, Empty);
}
}
handler.queuedEvents.Clear();
}),
new BeatAction.Action(beat, delegate
{
JJ.UnHold();
})
});
}
}

View file

@ -31,7 +31,8 @@ namespace HeavenStudio.Games.Scripts_WorkingDough
if (startBeat > double.MinValue)
{
Vector3 pos = GetPathPositionFromBeat(path, Math.Max(beat, startBeat), startBeat);
transform.position = pos;
if (startBeat <= beat) transform.position = pos;
else transform.position = new Vector3(-80, -80);
if (beat >= startBeat + 2) Destroy(gameObject);
}
}

View file

@ -2,7 +2,6 @@ using HeavenStudio.Util;
using System;
using System.Collections.Generic;
using UnityEngine;
using NaughtyBezierCurves;
namespace HeavenStudio.Games.Loaders
{
@ -15,26 +14,23 @@ namespace HeavenStudio.Games.Loaders
{
new GameAction("beat intervals", "Start Interval")
{
preFunction = delegate { var e = eventCaller.currentEntity; WorkingDough.PreSetIntervalStart(e.beat, e.length); },
preFunction = delegate { var e = eventCaller.currentEntity; WorkingDough.PreSetIntervalStart(e.beat, e.length, e["auto"]); },
defaultLength = 8f,
resizable = true,
priority = 2,
parameters = new List<Param>()
{
new Param("auto", true, "Auto Pass Turn", "Will the turn automatically be passed at the end of this event?")
}
},
new GameAction("small ball", "Small Ball")
{
preFunction = delegate { var e = eventCaller.currentEntity; WorkingDough.PreSpawnBall(e.beat, false, false); },
defaultLength = 0.5f,
priority = 1,
inactiveFunction = delegate { var e = eventCaller.currentEntity; WorkingDough.OnSpawnBallInactive(e.beat, false, false); },
function = delegate { var e = eventCaller.currentEntity; WorkingDough.instance.OnSpawnBall(e.beat, false, false); }
},
new GameAction("big ball", "Big Ball")
{
preFunction = delegate { var e = eventCaller.currentEntity; WorkingDough.PreSpawnBall(e.beat, true, e["hasGandw"]); },
defaultLength = 0.5f,
priority = 1,
inactiveFunction = delegate { var e = eventCaller.currentEntity; WorkingDough.OnSpawnBallInactive(e.beat, true, e["hasGandw"]); },
function = delegate { var e = eventCaller.currentEntity; WorkingDough.instance.OnSpawnBall(e.beat, true, e["hasGandw"]); },
parameters = new List<Param>()
{
new Param("hasGandw", false, "Has Mr. Game & Watch")
@ -103,8 +99,12 @@ namespace HeavenStudio.Games.Loaders
},
new GameAction("disableBG", "Toggle Background")
{
function = delegate { WorkingDough.instance.DisableBG(); },
defaultLength = 0.5f
function = delegate { WorkingDough.instance.DisableBG(eventCaller.currentEntity["ship"]); },
defaultLength = 0.5f,
parameters = new List<Param>()
{
new Param("ship", false, "Spaceship Only", "Will only the spaceship be affected by this event?")
}
}
},
new List<string>() {"rvl", "repeat"},
@ -117,6 +117,7 @@ namespace HeavenStudio.Games.Loaders
namespace HeavenStudio.Games
{
using Jukebox;
using Scripts_WorkingDough;
public class WorkingDough : Minigame
@ -154,6 +155,7 @@ namespace HeavenStudio.Games
[SerializeField] Animator gandwAnim;
[SerializeField] private GameObject[] bgObjects;
[SerializeField] private GameObject shipObject;
private bool bgDisabled;
[Header("Variables")]
@ -165,14 +167,7 @@ namespace HeavenStudio.Games
double gandMovingStartBeat;
public bool bigMode;
public bool bigModePlayer;
static List<QueuedBall> queuedBalls = new List<QueuedBall>();
static List<double> passedTurns = new List<double>();
struct QueuedBall
{
public double beat;
public bool isBig;
public bool hasGandw;
}
public bool spaceshipRisen = false;
public bool spaceshipRising = false;
bool liftingDoughDudes;
@ -215,10 +210,6 @@ namespace HeavenStudio.Games
void Awake()
{
if (crHandlerInstance == null)
{
crHandlerInstance = new CallAndResponseHandler(8);
}
instance = this;
}
@ -228,24 +219,68 @@ namespace HeavenStudio.Games
doughDudesHolderAnim.Play("OnGround", 0, 0);
}
public void DisableBG()
private bool shipOnly;
public void DisableBG(bool ship)
{
shipOnly = ship;
bgDisabled = !bgDisabled;
foreach (var bgObject in bgObjects)
{
bgObject.SetActive(!bgDisabled);
bgObject.SetActive(!bgDisabled || shipOnly);
}
shipObject.SetActive(!bgDisabled && !shipOnly);
}
public void SetIntervalStart(double beat, float interval)
private static List<RiqEntity> GetAllBallsInBetweenBeat(double beat, double endBeat)
{
if (!crHandlerInstance.IntervalIsActive())
List<RiqEntity> ballEvents = EventCaller.GetAllInGameManagerList("workingDough", new string[] { "small ball", "big ball" });
List<RiqEntity> tempEvents = new();
foreach (var entity in ballEvents)
{
bigMode = false;
if (entity.beat >= beat && entity.beat < endBeat)
{
tempEvents.Add(entity);
}
}
return tempEvents;
}
public void SetIntervalStart(double beat, double gameSwitchBeat, float interval = 8f, bool autoPassTurn = true)
{
CallAndResponseHandler newHandler = new();
crHandlerInstance = newHandler;
crHandlerInstance.StartInterval(beat, interval);
List<RiqEntity> relevantBalls = GetAllBallsInBetweenBeat(beat, beat + interval);
bool hasBigBall = false;
foreach (var ball in relevantBalls)
{
bool isBig = ball.datamodel == "workingDough/big ball";
if (ball.beat >= gameSwitchBeat)
{
SpawnBall(ball.beat - 1, isBig, isBig && ball["hasGandw"]);
OnSpawnBall(ball.beat, isBig, isBig && ball["hasGandw"]);
}
else
{
OnSpawnBallInactive(ball.beat, isBig, isBig && ball["hasGandw"]);
}
if (isBig) hasBigBall = true;
}
if (autoPassTurn)
{
PassTurn(beat + interval, interval, newHandler);
}
BeatAction.New(ballTransporterLeftNPC, new List<BeatAction.Action>()
{
new BeatAction.Action(beat - 1, delegate
{
bigMode = hasBigBall;
if (bigMode)
{
NPCBallTransporters.GetComponent<Animator>().Play("NPCGoBigMode", 0, 0);
}
if (!instance.ballTransporterLeftNPC.GetComponent<Animator>().IsPlayingAnimationName("BallTransporterLeftOpened"))
{
instance.ballTransporterLeftNPC.GetComponent<Animator>().Play("BallTransporterLeftOpen", 0, 0);
@ -253,48 +288,14 @@ namespace HeavenStudio.Games
if (instance.gandwHasEntered && !bgDisabled) instance.gandwAnim.Play("GANDWLeverUp", 0, 0);
}
}),
//Open player transporters
/*
new BeatAction.Action(beat + interval - 1f, delegate {
ballTransporterRightPlayer.GetComponent<Animator>().Play("BallTransporterRightOpen", 0, 0);
}),
new BeatAction.Action(beat + interval - 1f, delegate {
ballTransporterRightPlayer.GetComponent<Animator>().Play("BallTransporterRightOpen", 0, 0);
}),*/
//Close npc transporters
new BeatAction.Action(beat + interval, delegate {
if (bigMode)
{
NPCBallTransporters.GetComponent<Animator>().Play("NPCExitBigMode", 0, 0);
bigMode = false;
}
}),
/*
new BeatAction.Action(beat + interval + 1, delegate { if (!intervalStarted) ballTransporterLeftNPC.GetComponent<Animator>().Play("BallTransporterLeftClose", 0, 0); }),
new BeatAction.Action(beat + interval + 1, delegate { if (!intervalStarted) ballTransporterRightNPC.GetComponent<Animator>().Play("BallTransporterRightClose", 0, 0); }),
new BeatAction.Action(beat + interval + 1, delegate { if (gandwHasEntered) gandwAnim.Play("MrGameAndWatchLeverDown", 0, 0); }),
//Close player transporters
new BeatAction.Action(beat + interval * 2 + 1, delegate { ballTransporterLeftPlayer.GetComponent<Animator>().Play("BallTransporterLeftClose", 0, 0); }),
new BeatAction.Action(beat + interval * 2 + 1, delegate { ballTransporterRightPlayer.GetComponent<Animator>().Play("BallTransporterRightClose", 0, 0); }),
new BeatAction.Action(beat + interval * 2 + 1, delegate {
if (bigModePlayer)
{
PlayerBallTransporters.GetComponent<Animator>().Play("PlayerExitBigMode", 0, 0);
bigModePlayer = false;
}
}),
*/
});
}
crHandlerInstance.StartInterval(beat, interval);
}
public static void PrePassTurn(double beat)
{
if (GameManager.instance.currentGame == "workingDough")
{
instance.PassTurn(beat);
instance.PassTurnStandalone(beat);
}
else
{
@ -302,37 +303,54 @@ namespace HeavenStudio.Games
}
}
private void PassTurn(double beat)
private void PassTurnStandalone(double beat)
{
if (crHandlerInstance.queuedEvents.Count > 0)
if (crHandlerInstance != null) PassTurn(beat, crHandlerInstance.intervalLength, crHandlerInstance);
}
private void PassTurn(double beat, double length, CallAndResponseHandler crHandler)
{
BeatAction.New(instance.gameObject, new List<BeatAction.Action>()
{
new BeatAction.Action(beat - 1, delegate
{
ballTransporterRightPlayer.GetComponent<Animator>().Play("BallTransporterRightOpen", 0, 0);
ballTransporterLeftPlayer.GetComponent<Animator>().Play("BallTransporterLeftOpen", 0, 0);
foreach (var ball in crHandlerInstance.queuedEvents)
if (crHandler.queuedEvents.Count > 0)
{
bool hasBig = false;
foreach (var ball in crHandler.queuedEvents)
{
SpawnPlayerBall(beat + ball.relativeBeat - 1, ball.tag == "big", ball["hasGandw"]);
if (ball.tag == "big") hasBig = true;
}
crHandlerInstance.queuedEvents.Clear();
BeatAction.New(instance.gameObject, new List<BeatAction.Action>()
crHandler.queuedEvents.Clear();
bigModePlayer = hasBig;
if (bigModePlayer)
{
new BeatAction.Action(beat, delegate
{
if (crHandlerInstance.queuedEvents.Count > 0)
{
foreach (var ball in crHandlerInstance.queuedEvents)
{
SpawnPlayerBall(beat + ball.relativeBeat - 1, ball.tag == "big", ball["hasGandw"]);
PlayerBallTransporters.GetComponent<Animator>().Play("PlayerGoBigMode", 0, 0);
}
crHandlerInstance.queuedEvents.Clear();
}
}),
new BeatAction.Action(beat + 1, delegate { if (!crHandlerInstance.IntervalIsActive()) ballTransporterLeftNPC.GetComponent<Animator>().Play("BallTransporterLeftClose", 0, 0); }),
new BeatAction.Action(beat + 1, delegate { if (!crHandlerInstance.IntervalIsActive()) ballTransporterRightNPC.GetComponent<Animator>().Play("BallTransporterRightClose", 0, 0); }),
new BeatAction.Action(beat + 1, delegate { if (gandwHasEntered && !bgDisabled) gandwAnim.Play("MrGameAndWatchLeverDown", 0, 0); }),
new BeatAction.Action(beat + 1, delegate
{
if (gandwHasEntered && !bgDisabled) gandwAnim.Play("MrGameAndWatchLeverDown", 0, 0);
if (crHandlerInstance == null || !crHandlerInstance.IntervalIsActive())
{
ballTransporterLeftNPC.GetComponent<Animator>().Play("BallTransporterLeftClose", 0, 0);
ballTransporterRightNPC.GetComponent<Animator>().Play("BallTransporterRightClose", 0, 0);
}
if (bigMode)
{
NPCBallTransporters.GetComponent<Animator>().Play("NPCExitBigMode", 0, 0);
bigMode = false;
}
}),
//Close player transporters
new BeatAction.Action(beat + crHandlerInstance.intervalLength + 1, delegate { ballTransporterLeftPlayer.GetComponent<Animator>().Play("BallTransporterLeftClose", 0, 0); }),
new BeatAction.Action(beat + crHandlerInstance.intervalLength + 1, delegate { ballTransporterRightPlayer.GetComponent<Animator>().Play("BallTransporterRightClose", 0, 0); }),
new BeatAction.Action(beat + crHandlerInstance.intervalLength + 1, delegate {
new BeatAction.Action(beat + length + 1, delegate
{
ballTransporterLeftPlayer.GetComponent<Animator>().Play("BallTransporterLeftClose", 0, 0);
ballTransporterRightPlayer.GetComponent<Animator>().Play("BallTransporterRightClose", 0, 0);
if (bigModePlayer)
{
PlayerBallTransporters.GetComponent<Animator>().Play("PlayerExitBigMode", 0, 0);
@ -341,7 +359,6 @@ namespace HeavenStudio.Games
}),
});
}
}
public void SpawnBall(double beat, bool isBig, bool hasGandw)
{
@ -351,19 +368,10 @@ namespace HeavenStudio.Games
var ballComponent = spawnedBall.GetComponent<NPCDoughBall>();
spawnedBall.SetActive(true);
ballComponent.Init(beat, hasGandw);
if (isBig && !bigMode)
{
NPCBallTransporters.GetComponent<Animator>().Play("NPCGoBigMode", 0, 0);
bigMode = true;
}
arrowSRLeftNPC.sprite = redArrowSprite;
BeatAction.New(doughDudesNPC, new List<BeatAction.Action>()
{
//Jump and play sound
new BeatAction.Action(beat, delegate { arrowSRLeftNPC.sprite = redArrowSprite; }),
new BeatAction.Action(beat + 0.1f, delegate { arrowSRLeftNPC.sprite = whiteArrowSprite; }),
new BeatAction.Action(beat + 1f, delegate { doughDudesNPC.GetComponent<Animator>().DoScaledAnimationAsync(isBig ? "BigDoughJump" :"SmallDoughJump", 0.5f); }),
new BeatAction.Action(beat + 1f, delegate { npcImpact.SetActive(true); }),
@ -373,43 +381,11 @@ namespace HeavenStudio.Games
});
}
public static void PreSpawnBall(double beat, bool isBig, bool hasGandw)
{
double spawnBeat = beat - 1f;
beat -= 1f;
if (GameManager.instance.currentGame == "workingDough")
{
BeatAction.New(instance.gameObject, new List<BeatAction.Action>()
{
new BeatAction.Action(spawnBeat, delegate
{
if (!instance.ballTransporterLeftNPC.GetComponent<Animator>().IsPlayingAnimationName("BallTransporterLeftOpened") && !crHandlerInstance.IntervalIsActive() && !instance.bgDisabled)
{
instance.ballTransporterLeftNPC.GetComponent<Animator>().Play("BallTransporterLeftOpen", 0, 0);
instance.ballTransporterRightNPC.GetComponent<Animator>().Play("BallTransporterRightOpen", 0, 0);
if (instance.gandwHasEntered) instance.gandwAnim.Play("GANDWLeverUp", 0, 0);
}
}),
new BeatAction.Action(spawnBeat, delegate { if (instance != null) instance.SpawnBall(beat, isBig, hasGandw); }),
// new BeatAction.Action(spawnBeat + instance.beatInterval, delegate { instance.SpawnPlayerBall(beat + instance.beatInterval, isBig); }),
});
}
else
{
queuedBalls.Add(new QueuedBall()
{
beat = beat + 1f,
isBig = isBig,
hasGandw = hasGandw
});
}
}
public static void OnSpawnBallInactive(double beat, bool isBig, bool hasGandw)
{
if (crHandlerInstance == null)
{
crHandlerInstance = new CallAndResponseHandler(8);
crHandlerInstance = new CallAndResponseHandler();
}
crHandlerInstance.AddEvent(beat, 0, isBig ? "big" : "small", new List<CallAndResponseHandler.CallAndResponseEventParam>()
{
@ -423,17 +399,8 @@ namespace HeavenStudio.Games
{
new CallAndResponseHandler.CallAndResponseEventParam("hasGandw", hasGandw)
});
SoundByte.PlayOneShotGame(isBig ? "workingDough/hitBigOther" : "workingDough/hitSmallOther");
SoundByte.PlayOneShotGame(isBig ? "workingDough/bigOther" : "workingDough/smallOther");
}
public static void InactiveInterval(double beat, float interval)
{
if (crHandlerInstance == null)
{
crHandlerInstance = new CallAndResponseHandler(8);
}
crHandlerInstance.StartInterval(beat, interval);
SoundByte.PlayOneShotGame(isBig ? "workingDough/hitBigOther" : "workingDough/hitSmallOther", beat);
SoundByte.PlayOneShotGame(isBig ? "workingDough/bigOther" : "workingDough/smallOther", beat);
}
public void SpawnPlayerBall(double beat, bool isBig, bool hasGandw)
@ -445,12 +412,6 @@ namespace HeavenStudio.Games
spawnedBall.SetActive(true);
ballComponent.Init(beat, isBig, hasGandw);
if (isBig && !bigModePlayer)
{
PlayerBallTransporters.GetComponent<Animator>().Play("PlayerGoBigMode", 0, 0);
bigModePlayer = true;
}
BeatAction.New(doughDudesPlayer, new List<BeatAction.Action>()
{
new BeatAction.Action(beat, delegate { arrowSRLeftPlayer.sprite = redArrowSprite; }),
@ -458,17 +419,30 @@ namespace HeavenStudio.Games
});
}
public static void PreSetIntervalStart(double beat, float interval)
private struct QueuedInterval
{
public double beat;
public float interval;
public bool auto;
}
private static List<QueuedInterval> queuedIntervals = new();
public static void PreSetIntervalStart(double beat, float interval, bool auto)
{
if (GameManager.instance.currentGame == "workingDough")
{
// instance.ballTriggerSetInterval = false;
// beatInterval = interval;
instance.SetIntervalStart(beat, interval);
instance.SetIntervalStart(beat, beat, interval, auto);
}
else
{
InactiveInterval(beat, interval);
queuedIntervals.Add(new QueuedInterval
{
beat = beat,
interval = interval,
auto = auto
});
}
}
@ -478,7 +452,6 @@ namespace HeavenStudio.Games
{
crHandlerInstance = null;
}
if (queuedBalls.Count > 0) queuedBalls.Clear();
foreach (var evt in scheduledInputs)
{
evt.Disable();
@ -487,38 +460,26 @@ namespace HeavenStudio.Games
public override void OnGameSwitch(double beat)
{
if (queuedBalls.Count > 0)
if (Conductor.instance.isPlaying && !Conductor.instance.isPaused)
{
foreach (var ball in queuedBalls)
if (queuedIntervals.Count > 0)
{
if (ball.isBig) NPCBallTransporters.GetComponent<Animator>().Play("BigMode", 0, 0);
if (!crHandlerInstance.IntervalIsActive())
foreach (var interval in queuedIntervals)
{
ballTransporterLeftNPC.GetComponent<Animator>().Play("BallTransporterLeftOpened", 0, 0);
ballTransporterRightNPC.GetComponent<Animator>().Play("BallTransporterRightOpened", 0, 0);
if (gandwHasEntered && !bgDisabled) gandwAnim.Play("GANDWLeverUp", 0, 0);
SetIntervalStart(interval.beat, beat, interval.interval, interval.auto);
}
queuedIntervals.Clear();
}
}
if (ball.beat > beat - 1)
{
BeatAction.New(instance.gameObject, new List<BeatAction.Action>()
{
new BeatAction.Action(ball.beat - 1, delegate { SpawnBall(ball.beat - 1, ball.isBig, ball.hasGandw); })
});
}
}
queuedBalls.Clear();
}
public override void OnPlay(double beat)
{
crHandlerInstance = null;
}
void Update()
{
Conductor cond = Conductor.instance;
if (!cond.isPlaying || cond.isPaused)
{
if (queuedBalls.Count > 0) queuedBalls.Clear();
}
if (spaceshipRising && !bgDisabled) spaceshipAnimator.DoScaledAnimation("RiseSpaceship", risingStartBeat, risingLength);
if (liftingDoughDudes && !bgDisabled) doughDudesHolderAnim.DoScaledAnimation(liftingAnimName, liftingStartBeat, liftingLength);
if (gandwMoving && !bgDisabled) gandwAnim.DoScaledAnimation(gandwMovingAnimName, gandMovingStartBeat, gandMovingLength);
@ -526,7 +487,7 @@ namespace HeavenStudio.Games
{
foreach (var passTurn in passedTurns)
{
PassTurn(passTurn);
PassTurnStandalone(passTurn);
}
passedTurns.Clear();
}