HeavenStudioPlus/Assets/Scripts/Games/GleeClub/GleeClub.cs
Zeo e50e4e39e0
Mass Text Update (#615)
* Air Rally Text Update

* Blue Bear Text Update

* Board Meeting Text Update

* Built To Scale DS Text Update

also changed Air Rally's assetbundle tag from "normal" to "keep"

* Catchy Tune Text Update

also changed some minor wording in Board Meeting and Built To Scale DS

* Cheer Readers Text Update

* The Clappy Trio Text Update

* Coin Toss Text Update

* Crop Stomp Text Update

* DJ School Text Update

* Dog Ninja Text Update

* Double Date Text Update

* Drumming Practice Text Update

* Fan Club Text Update

* Fireworks Text Update

* Second Contact Text Update

* Flipper-Flop Text Update

also fix an error in Catchy Tune

* Fork Lifter Text Update

* Glee Club Text Update

* Karate Man Text Update

also minor updates to other games

* Kitties! Text Update

* Launch Party Text Update

* Lockstep Text Update

* Marching Orders Text Update

* Meat Grinder Text Update

also fixed an error in Second Contact

* Mr. Upbeat Text Update

* Munchy Monk Text Update

* Octopus Machine Text Update

* Pajama Party Text Update

* Quiz Show Text Update

also changed some wording in meat grinder

* Rhythm Rally Text Update

* Rhythm Somen Text Update

that was easy

* Rhythm Tweezers Text Update

* Ringside Text Update

* Rockers Text Update

this sucked

* Samurai Slice DS Text Update

* See Saw Text Update

* Sneaky Spirits Text Update

* Spaceball Text Update

* Space Dance Text Update

* Space Soccer Text Update

* Splashdown Text Update

* Tambourine Text Update

* Tap Trial Text Update

* Tap Troupe Text Update

* The Dazzles Text Update

* Toss Boys Text Update

* Tram & Pauline Text Update

also added translation for Fireworks

* Tunnel Text Update

* Wizard's Waltz Text Update

* Working Dough Text Update

* fix compiler errors

* fix editor offset bug(?)

* fix missing param in second contact

* Ball Redispense text

* remove space soccer swing

* Trick on the Class Text Update

* Non-Game Text Update

* fix pre-function sorting

* camera shake ease

* remove a bunch of prints

* rhythm tweezers bug fix

* Update Credits.txt

* ssds nop samurai bop

* swap order of shake properties

* Update FirstContact.cs

---------

Co-authored-by: minenice55 <star.elementa@gmail.com>
2024-01-15 02:04:10 +00:00

510 lines
23 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using HeavenStudio.Util;
using HeavenStudio.InputSystem;
using Jukebox;
namespace HeavenStudio.Games.Loaders
{
using static Minigames;
public static class NtrGleeClubLoader
{
public static Minigame AddGame(EventCaller eventCaller)
{
return new Minigame("gleeClub", "Glee Club", "cfcecf", false, false, new List<GameAction>()
{
new GameAction("intervalStart", "Start Interval")
{
defaultLength = 1f,
resizable = true
},
new GameAction("sing", "Sing")
{
function = delegate { var e = eventCaller.currentEntity; GleeClub.instance.Sing(e.beat, e.length, e["semiTones"], e["semiTones1"], e["semiTonesPlayer"],
e["close"], e["repeat"], e["semiTonesLeft2"], e["semiTonesLeft3"], e["semiTonesMiddle2"]); },
resizable = true,
parameters = new List<Param>()
{
new Param("semiTones", new EntityTypes.Integer(-24, 24, -5), "Semitones", "Set the number of semitones up or down this note should be pitched."),
new Param("semiTones1", new EntityTypes.Integer(-24, 24, -1), "Semitones (Next)", "Set the number of semitones up or down this note should be pitched."),
new Param("semiTonesPlayer", new EntityTypes.Integer(-24, 24, 2), "Semitones (Player)", "Set the number of semitones up or down this note should be pitched."),
new Param("close", GleeClub.MouthOpenClose.Both, "Close/Open Mouth", "Choose if the chorus kids should close or open their mouth."),
new Param("repeat", false, "Repeating", "Toggle if the left and middle chorus kid should repeat this singing cue.", new List<Param.CollapseParam>()
{
new Param.CollapseParam((x, _) => (bool)x, new string[] { "semiTonesLeft2", "semiTonesLeft3", "semiTonesMiddle2" })
}),
new Param("semiTonesLeft2", new EntityTypes.Integer(-24, 24, 0), "Semitones (Repeat Left First)", "Set the number of semitones up or down this note should be pitched."),
new Param("semiTonesLeft3", new EntityTypes.Integer(-24, 24, 0), "Semitones (Repeat Left Last)", "Set the number of semitones up or down this note should be pitched."),
new Param("semiTonesMiddle2", new EntityTypes.Integer(-24, 24, 0), "Semitones (Repeat Middle)", "Set the number of semitones up or down this note should be pitched."),
}
},
new GameAction("baton", "Baton")
{
preFunction = delegate { var e = eventCaller.currentEntity; GleeClub.PreBaton(e.beat); },
defaultLength = 2f
},
new GameAction("togetherNow", "Together Now!")
{
function = delegate { var e = eventCaller.currentEntity; GleeClub.instance.TogetherNow(e.beat, e["semiTones"], e["semiTones1"], e["semiTonesPlayer"], e["pitch"]); },
defaultLength = 4f,
parameters = new List<Param>()
{
new Param("semiTones", new EntityTypes.Integer(-24, 24, -1), "Semitones", "Set the number of semitones up or down this note should be pitched."),
new Param("semiTones1", new EntityTypes.Integer(-24, 24, 4), "Semitones (Next)", "Set the number of semitones up or down this note should be pitched."),
new Param("semiTonesPlayer", new EntityTypes.Integer(-24, 24, 10), "Semitones (Player)", "Set the number of semitones up or down this note should be pitched."),
new Param("pitch", new EntityTypes.Float(0f, 5f, 1f), "Conductor Voice Pitch", "Choose the pitch of the conductor's voice. 1 is normal pitch.")
}
},
new GameAction("forceSing", "Force Sing")
{
function = delegate { var e = eventCaller.currentEntity; GleeClub.instance.ForceSing(e["semiTones"], e["semiTones1"], e["semiTonesPlayer"]); },
defaultLength = 0.5f,
parameters = new List<Param>()
{
new Param("semiTones", new EntityTypes.Integer(-24, 24, 0), "Semitones", "Set the number of semitones up or down this note should be pitched."),
new Param("semiTones1", new EntityTypes.Integer(-24, 24, 0), "Semitones (Next)", "Set the number of semitones up or down this note should be pitched."),
new Param("semiTonesPlayer", new EntityTypes.Integer(-24, 24, 0), "Semitones (Player)", "Set the number of semitones up or down this note should be pitched."),
}
},
new GameAction("presence", "Toggle Chorus Kids")
{
function = delegate { var e = eventCaller.currentEntity; GleeClub.instance.ToggleKidsPresence(!e["left"], !e["middle"], !e["player"]); },
defaultLength = 0.5f,
parameters = new List<Param>()
{
new Param("left", false, "Left Kid Present", "Toggle if this chorus kid should be present."),
new Param("middle", false, "Middle Kid Present", "Toggle if this chorus kid should be present."),
new Param("player", false, "Player Kid Present", "Toggle if this chorus kid should be present."),
}
},
new GameAction("fadeOutTime", "Set Sing Game-Switch Fade Out Time")
{
function = delegate { var e = eventCaller.currentEntity; GleeClub.instance.SetGameSwitchFadeOutTime(e["fade"], e["fade1"], e["fadeP"]); },
defaultLength = 0.5f,
parameters = new List<Param>()
{
new Param("fade", new EntityTypes.Float(0, 20f, 0f), "Left Chorus Kid", "Set how long (in seconds) this chorus kid's singing should take to fade out if it is interrupted by a game switch."),
new Param("fade1", new EntityTypes.Float(0, 20f, 0f), "Middle Chorus Kid", "Set how long (in seconds) this chorus kid's singing should take to fade out if it is interrupted by a game switch."),
new Param("fadeP", new EntityTypes.Float(0, 20f, 0f), "Player Chorus Kid", "Set how long (in seconds) this chorus kid's singing should take to fade out if it is interrupted by a game switch."),
}
},
new GameAction("passTurn", "Pass Turn")
{
function = delegate { var e = eventCaller.currentEntity; GleeClub.instance.PassTurn(e.beat, e.length); },
resizable = true,
defaultLength = 0.5f,
hidden = true
},
},
new List<string>() { "ntr", "repeat" },
"ntrchorus", "en",
new List<string>() { "en" }
);
}
}
}
namespace HeavenStudio.Games
{
using Scripts_GleeClub;
public class GleeClub : Minigame
{
public enum MouthOpenClose
{
Both,
OnlyOpen,
OnlyClose
}
public struct QueuedSinging
{
public double startBeat;
public float length;
public int semiTones;
public int semiTonesPlayer;
public int closeMouth;
public bool repeating;
public int semiTonesLeft2;
public int semiTonesLeft3;
public int semiTonesMiddle2;
}
[Header("Prefabs")]
[SerializeField] GleeClubSingInput singInputPrefab;
[Header("Components")]
[SerializeField] Animator heartAnim;
[SerializeField] Animator condAnim;
public ChorusKid leftChorusKid;
public ChorusKid middleChorusKid;
public ChorusKid playerChorusKid;
[Header("Variables")]
static List<QueuedSinging> queuedSingings = new List<QueuedSinging>();
static List<double> queuedBatons = new();
bool intervalStarted;
double intervalStartBeat;
float beatInterval = 4f;
public bool missed;
public static GleeClub instance;
float currentYellPitch = 1f;
int startIntervalIndex;
private List<RiqEntity> allIntervalEvents = new List<RiqEntity>();
void Awake()
{
instance = this;
var camEvents = EventCaller.GetAllInGameManagerList("gleeClub", new string[] { "intervalStart" });
List<RiqEntity> tempEvents = new List<RiqEntity>();
for (int i = 0; i < camEvents.Count; i++)
{
if (camEvents[i].beat + camEvents[i].beat >= Conductor.instance.songPositionInBeatsAsDouble)
{
tempEvents.Add(camEvents[i]);
}
}
allIntervalEvents = tempEvents;
}
void Start()
{
if (!PlayerInput.GetIsAction(InputAction_BasicPressing) && Conductor.instance.isPlaying && !GameManager.instance.autoplay)
{
playerChorusKid.StartSinging();
leftChorusKid.MissPose();
middleChorusKid.MissPose();
}
}
void OnDestroy()
{
if (!Conductor.instance.isPlaying || Conductor.instance.isPaused)
{
if (queuedSingings.Count > 0) queuedSingings.Clear();
if (queuedBatons.Count > 0) queuedBatons.Clear();
}
foreach (var evt in scheduledInputs)
{
evt.Disable();
}
}
void Update()
{
if (!playerChorusKid.disappeared)
{
if (PlayerInput.GetIsAction(InputAction_BasicPress) && !IsExpectingInputNow(InputAction_BasicPress))
{
playerChorusKid.StopSinging();
leftChorusKid.MissPose();
middleChorusKid.MissPose();
ScoreMiss();
}
if (PlayerInput.GetIsAction(InputAction_BasicRelease) && !IsExpectingInputNow(InputAction_BasicRelease))
{
playerChorusKid.StartSinging();
leftChorusKid.MissPose();
middleChorusKid.MissPose();
ScoreMiss();
}
if (PlayerInput.GetIsAction(InputAction_FlickRelease) && !IsExpectingInputNow(InputAction_FlickRelease))
{
if (PlayerInput.CurrentControlStyle == InputController.ControlStyles.Touch)
{
playerChorusKid.StartYell();
leftChorusKid.MissPose();
middleChorusKid.MissPose();
ScoreMiss();
}
}
}
if (Conductor.instance.isPlaying && !Conductor.instance.isPaused)
{
if (queuedBatons.Count > 0)
{
foreach (var baton in queuedBatons)
{
Baton(baton);
}
queuedBatons.Clear();
}
float normalizedBeat = Conductor.instance.GetPositionFromBeat(intervalStartBeat, beatInterval);
if (normalizedBeat >= 1f && intervalStarted)
{
PassTurn(intervalStartBeat + beatInterval, 0f);
}
if (allIntervalEvents.Count > 0)
{
if (startIntervalIndex < allIntervalEvents.Count && startIntervalIndex >= 0)
{
if (Conductor.instance.songPositionInBeatsAsDouble >= allIntervalEvents[startIntervalIndex].beat)
{
StartInterval((float)allIntervalEvents[startIntervalIndex].beat, allIntervalEvents[startIntervalIndex].length);
startIntervalIndex++;
}
}
}
}
if (!Conductor.instance.isPlaying || Conductor.instance.isPaused)
{
if (queuedSingings.Count > 0) queuedSingings.Clear();
if (queuedBatons.Count > 0) queuedBatons.Clear();
}
}
public void ToggleKidsPresence(bool left, bool middle, bool player)
{
leftChorusKid.TogglePresence(left);
middleChorusKid.TogglePresence(middle);
playerChorusKid.TogglePresence(player);
}
public void SetGameSwitchFadeOutTime(float fadeOut, float fadeOut1, float fadeOutPlayer)
{
leftChorusKid.gameSwitchFadeOutTime = fadeOut;
middleChorusKid.gameSwitchFadeOutTime = fadeOut1;
playerChorusKid.gameSwitchFadeOutTime = fadeOutPlayer;
}
public void ForceSing(int semiTones, int semiTones1, int semiTonesPlayer)
{
leftChorusKid.currentPitch = SoundByte.GetPitchFromSemiTones(semiTones, true);
middleChorusKid.currentPitch = SoundByte.GetPitchFromSemiTones(semiTones1, true);
playerChorusKid.currentPitch = SoundByte.GetPitchFromSemiTones(semiTonesPlayer, true);
leftChorusKid.StartSinging(true);
middleChorusKid.StartSinging(true);
if (!PlayerInput.GetIsAction(InputAction_BasicPressing) || GameManager.instance.autoplay) playerChorusKid.StartSinging(true);
else missed = true;
}
public void TogetherNow(double beat, int semiTones, int semiTones1, int semiTonesPlayer, float conductorPitch)
{
if (!playerChorusKid.disappeared) ScheduleInput(beat, 2.5f, InputAction_FlickRelease, JustTogetherNow, Out, Out);
if (!playerChorusKid.disappeared) ScheduleInput(beat, 3.5f, InputAction_BasicPress, JustTogetherNowClose, MissBaton, Out);
float pitch = SoundByte.GetPitchFromSemiTones(semiTones, true);
float pitch1 = SoundByte.GetPitchFromSemiTones(semiTones1, true);
currentYellPitch = SoundByte.GetPitchFromSemiTones(semiTonesPlayer, true);
MultiSound.Play(new MultiSound.Sound[]
{
new MultiSound.Sound("gleeClub/togetherEN-01", beat + 0.5f, conductorPitch),
new MultiSound.Sound("gleeClub/togetherEN-02", beat + 1f, conductorPitch),
new MultiSound.Sound("gleeClub/togetherEN-03", beat + 1.5f, conductorPitch),
new MultiSound.Sound("gleeClub/togetherEN-04", beat + 2f, conductorPitch, 1, false, 0.02f),
});
BeatAction.New(instance, new List<BeatAction.Action>()
{
new BeatAction.Action(beat + 1.5f, delegate
{
leftChorusKid.StartCrouch();
middleChorusKid.StartCrouch();
playerChorusKid.StartCrouch();
}),
new BeatAction.Action(beat + 2.5f, delegate
{
leftChorusKid.currentPitch = pitch;
middleChorusKid.currentPitch = pitch1;
leftChorusKid.StartYell();
middleChorusKid.StartYell();
}),
new BeatAction.Action(beat + 3.5f, delegate
{
leftChorusKid.StopSinging(true);
middleChorusKid.StopSinging(true);
}),
new BeatAction.Action(beat + 6f, delegate
{
if (!playerChorusKid.disappeared) ShowHeart(beat + 6f);
})
});
}
void JustTogetherNow(PlayerActionEvent caller, float state)
{
playerChorusKid.currentPitch = currentYellPitch;
playerChorusKid.StartYell();
}
void JustTogetherNowClose(PlayerActionEvent caller, float state)
{
playerChorusKid.StopSinging(true);
}
public void StartInterval(double beat, float length)
{
intervalStartBeat = beat;
beatInterval = length;
intervalStarted = true;
}
public void Sing(double beat, float length, int semiTones, int semiTones1, int semiTonesPlayer, int closeMouth, bool repeating, int semiTonesLeft2, int semiTonesLeft3, int semiTonesMiddle2)
{
float pitch = SoundByte.GetPitchFromSemiTones(semiTones, true);
if (!intervalStarted)
{
StartInterval(beat, length);
}
BeatAction.New(instance, new List<BeatAction.Action>()
{
new BeatAction.Action(beat, delegate { if (closeMouth != (int)MouthOpenClose.OnlyClose) leftChorusKid.currentPitch = pitch; leftChorusKid.StartSinging(); }),
new BeatAction.Action(beat + length, delegate { if (closeMouth != (int)MouthOpenClose.OnlyOpen) leftChorusKid.StopSinging(); }),
});
queuedSingings.Add(new QueuedSinging
{
startBeat = beat - intervalStartBeat,
length = length,
semiTones = semiTones1,
closeMouth = closeMouth,
semiTonesPlayer = semiTonesPlayer,
repeating = repeating,
semiTonesLeft2 = semiTonesLeft2,
semiTonesLeft3 = semiTonesLeft3,
semiTonesMiddle2 = semiTonesMiddle2
});
}
public void PassTurn(double beat, float length)
{
if (queuedSingings.Count == 0) return;
intervalStarted = false;
missed = false;
if (!playerChorusKid.disappeared) ShowHeart(beat + length + beatInterval * 2 + 1);
foreach (var sing in queuedSingings)
{
float playerPitch = SoundByte.GetPitchFromSemiTones(sing.semiTonesPlayer, true);
if (!playerChorusKid.disappeared)
{
GleeClubSingInput spawnedInput = Instantiate(singInputPrefab, transform);
spawnedInput.pitch = playerPitch;
spawnedInput.Init(beat + length + sing.startBeat + beatInterval, sing.length, sing.closeMouth);
}
float pitch = SoundByte.GetPitchFromSemiTones(sing.semiTones, true);
float pitchLeft2 = SoundByte.GetPitchFromSemiTones(sing.semiTonesLeft2, true);
float pitchLeft3 = SoundByte.GetPitchFromSemiTones(sing.semiTonesLeft3, true);
float pitchMiddle2 = SoundByte.GetPitchFromSemiTones(sing.semiTonesMiddle2, true);
BeatAction.New(instance, new List<BeatAction.Action>()
{
new BeatAction.Action(beat + length + sing.startBeat, delegate
{
if (sing.closeMouth != (int)MouthOpenClose.OnlyClose)
{
middleChorusKid.currentPitch = pitch;
middleChorusKid.StartSinging();
if (sing.repeating)
{
leftChorusKid.currentPitch = pitchLeft2;
leftChorusKid.StartSinging();
}
}
}),
new BeatAction.Action(beat + length + sing.startBeat + sing.length, delegate
{
if (sing.closeMouth != (int)MouthOpenClose.OnlyOpen)
{
middleChorusKid.StopSinging();
if (sing.repeating) leftChorusKid.StopSinging();
}
}),
new BeatAction.Action(beat + length + sing.startBeat + beatInterval, delegate
{
if (sing.closeMouth != (int)MouthOpenClose.OnlyClose && sing.repeating)
{
middleChorusKid.currentPitch = pitchMiddle2;
leftChorusKid.currentPitch = pitchLeft3;
middleChorusKid.StartSinging();
leftChorusKid.StartSinging();
}
}),
new BeatAction.Action(beat + length + sing.startBeat + sing.length + beatInterval, delegate
{
if (sing.closeMouth != (int)MouthOpenClose.OnlyOpen && sing.repeating)
{
middleChorusKid.StopSinging();
leftChorusKid.StopSinging();
}
}),
});
}
queuedSingings.Clear();
}
public static void PreBaton(double beat)
{
MultiSound.Play(new MultiSound.Sound[]
{
new MultiSound.Sound("gleeClub/BatonUp", beat),
new MultiSound.Sound("gleeClub/BatonDown", beat + 1),
}, forcePlay: true);
if (GameManager.instance.currentGame == "gleeClub")
{
instance.Baton(beat);
}
else
{
queuedBatons.Add(beat);
}
}
public void Baton(double beat)
{
missed = false;
if (!playerChorusKid.disappeared) ScheduleInput(beat, 1, InputAction_BasicPress, JustBaton, MissBaton, Out);
BeatAction.New(instance, new List<BeatAction.Action>()
{
new BeatAction.Action(beat, delegate
{
condAnim.DoScaledAnimationAsync("ConductorBatonUp", 0.5f);
}),
new BeatAction.Action(beat + 1, delegate
{
condAnim.DoScaledAnimationAsync("ConductorBatonDown", 0.5f);
leftChorusKid.StopSinging();
middleChorusKid.StopSinging();
}),
new BeatAction.Action(beat + 2, delegate
{
condAnim.DoUnscaledAnimation("ConductorIdle", 0, -1);
}),
});
}
void JustBaton(PlayerActionEvent caller, float state)
{
playerChorusKid.StopSinging();
ShowHeart(caller.timer + caller.startBeat + 1f);
}
void MissBaton(PlayerActionEvent caller)
{
missed = true;
}
void Out(PlayerActionEvent caller) { }
public void ShowHeart(double beat)
{
BeatAction.New(instance, new List<BeatAction.Action>()
{
new BeatAction.Action(beat, delegate
{
if (missed)
{
leftChorusKid.MissPose();
middleChorusKid.MissPose();
return;
}
heartAnim.Play("HeartIdle", 0, 0);
}),
new BeatAction.Action(beat + 2, delegate
{
heartAnim.Play("HeartNothing", 0, 0);
})
});
}
}
}