HeavenStudio/Assets/Scripts/Games/FreezeFrame/FreezeFrame.cs
playinful 281d318d38
Freeze Frame (#784)
* Freeze Frame

Hey, I'm about done with Freeze Frame and I'm just gonna commit the game as it is right now, it's almost done thx
-playinful

* Freeze Frame - finishing touches before finalized assets

Still waiting to implement the upscaled assets and the sound effects. Code-wise this is as much as I can do for now.

* i fixed a couple bugs

the dim screen is back and no input duplication when switching games. hallelujah

* FreezeFrame randomness update

hey AJ so i was cleaning my room when i was struck by an idea for how to make the randomization more consistent without seeding. *yes unfortunately* it requires a static variable but i promise u i used it responsibly.
2024-03-12 18:58:59 +00:00

1400 lines
59 KiB
C#

using System;
using System.Linq;
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 NtrFreezeFrameLoader
{
public static Minigame AddGame(EventCaller eventCaller)
{
return new Minigame("freezeFrame", "Freeze Frame", "8b93b4", false, false, new List<GameAction>()
{
new GameAction("bop", "Bop")
{
function = delegate { var e = eventCaller.currentEntity; FreezeFrame.SetBopping(e.beat, e.length, e["bop"], e["autoBop"], e["blink"], e["autoBlink"]); },
defaultLength = 1f,
resizable = true,
parameters = new List<Param>()
{
new Param("bop", false, "Bop", "Set the type of photo to use."),
new Param("autoBop", true, "Bop (Auto)", "Set the type of photo to use."),
new Param("blink", false, "Crosshair Blink", "Set the type of photo to use."),
new Param("autoBlink", true, "Crosshair Blink (Auto)", "Set the type of photo to use."),
}
},
// cues
new GameAction("slowCar", "Slow Car")
{
function = delegate { var e = eventCaller.currentEntity; FreezeFrame.SlowCarCue(e.beat, e["variant"]); },
defaultLength = 3f,
inactiveFunction = delegate { var e = eventCaller.currentEntity; if (!(bool)e["mute"]) FreezeFrame.SlowCarSFX(); },
parameters = new List<Param>()
{
new Param("variant", FreezeFrame.PhotoType.Random, "Photo Variant", "Set the type of photo to use."),
new Param("mute", false, "Mute", "Mute the sound of the cue."),
new Param("autoShowPhotos", true, "Auto Show Photos", "Automagically show the photos after they're taken.", new List<Param.CollapseParam>()
{
new Param.CollapseParam((x, _) => (bool)x, new string[] { "gradeType", "audience" })
}),
new Param("gradeType", FreezeFrame.GradeType.Symbols, "Rating Type", "Choose whether to use the English or Japanese variant of the grading screen."),
new Param("audience", true, "Crowd Cheer", "Set whether or not the audience should cheer when the photos are shown."),
}
},
new GameAction("fastCar", "Fast Car")
{
function = delegate { var e = eventCaller.currentEntity; FreezeFrame.FastCarCue(e.beat, e["variant"]); },
defaultLength = 3f,
inactiveFunction = delegate { var e = eventCaller.currentEntity; if (!(bool)e["mute"]) FreezeFrame.FastCarSFX(); },
parameters = new List<Param>()
{
new Param("variant", FreezeFrame.PhotoType.Random, "Photo Variant", "Set the type of photo to use."),
new Param("mute", false, "Mute", "Mute the sound of the cue."),
new Param("autoShowPhotos", true, "Auto Show Photos", "Automagically show the photos after they're taken.", new List<Param.CollapseParam>()
{
new Param.CollapseParam((x, _) => (bool)x, new string[] { "gradeType", "audience" })
}),
new Param("gradeType", FreezeFrame.GradeType.Symbols, "Rating Type", "Choose whether to use the English or Japanese variant of the grading screen."),
new Param("audience", true, "Crowd Cheer", "Set whether or not the audience should cheer when the photos are shown."),
}
},
new GameAction("showPhotos", "Show Photos")
{
function = delegate { var e = eventCaller.currentEntity; FreezeFrame.ShowPhotos(e.beat, e.length, e["gradeType"], e["audience"], e["clearCache"]); },
defaultLength = 1,
resizable = true,
parameters = new List<Param>()
{
new Param("gradeType", FreezeFrame.GradeType.Symbols, "Rating Type", "Choose whether to use the English or Japanese variant of the grading screen."),
new Param("audience", true, "Crowd Cheer", "Set whether or not the audience should cheer when the photos are shown."),
new Param("clearCache", true, "Clear Photos", "Clears the photo cache after the photos are shown."),
}
},
new GameAction("clearPhotos", "Clear Photo Cache")
{
function = delegate { var e = eventCaller.currentEntity; FreezeFrame.ClearPhotos(); },
inactiveFunction = delegate { var e = eventCaller.currentEntity; FreezeFrame.ClearPhotos(); },
defaultLength = 0.5f,
parameters = new List<Param>()
{
}
},
// distractions
new GameAction("spawnPerson", "Spawn Walker")
{
function = delegate { var e = eventCaller.currentEntity; FreezeFrame.SummonWalker(e); },
defaultLength = 4f,
resizable = true,
parameters = new List<Param>()
{
new Param("personType", FreezeFrame.PersonType.Dude1, "Walker Type", "Choose the type of walker to spawn."),
new Param("direction", FreezeFrame.PersonDirection.Random, "Direction", "Choose the direction from which to spawn the walker."),
new Param("layer", new EntityTypes.Integer(-10, 10, 0), "Layer", "The layer on which this walker should spawn (higher numbers are shown in front)."),
}
},
new GameAction("spawnCrowd", "Show/Hide Crowd")
{
function = delegate { var e = eventCaller.currentEntity; FreezeFrame.ToggleCrowd(e.beat, e["crowd"], e["customCrowd"], e["crowdFarLeft"], e["crowdLeft"], e["crowdRight"], e["crowdFarRight"], e["billboard"]); },
defaultLength = 0.5f,
parameters = new List<Param>()
{
new Param("crowd", true, "Show Crowd", "Choose whether to spawn or despawn the crowd."),
new Param("customCrowd", false, "Custom Crowd", "Select to customize the crowd.", new List<Param.CollapseParam>()
{
new Param.CollapseParam((x, _) => (bool)x, new string[] { "crowdFarLeft", "crowdLeft", "crowdRight", "crowdFarRight" })
}),
new Param("crowdFarLeft" , FreezeFrame.CustomCrowdType.PinkDancers, "Far Left" , "Select the graphic to display on the far left."),
new Param("crowdLeft" , FreezeFrame.CustomCrowdType.YellowDancers, "Center Left" , "Select the graphic to display on the near left."),
new Param("crowdRight" , FreezeFrame.CustomCrowdType.TealDancers, "Center Right", "Select the graphic to display on the near right."),
new Param("crowdFarRight", FreezeFrame.CustomCrowdType.PinkDancers, "Far Right" , "Select the graphic to display on the far right."),
new Param("billboard", false, "Show Billboard", "Choose whether to show or hide the billboards."),
}
},
new GameAction("introSign", "Intro Sign")
{
function = delegate { var e = eventCaller.currentEntity; FreezeFrame.DoIntroSign(e.beat, e.length, e["enter"], e["ease"]); },
defaultLength = 4f,
resizable = true,
parameters = new List<Param>()
{
new Param("enter", true, "Enter", "Choose the sign should enter or exit."),
new Param("ease", Util.EasingFunction.Ease.Linear, "Ease", "Set the easing of the action."),
}
},
new GameAction("introLights", "Intro Lights")
{
function = delegate { var e = eventCaller.currentEntity; FreezeFrame.IntroLightsAnim(e.beat, e.length, e["lightsOn"]); FreezeFrame.IntroLightsSound(e.beat, e.length, e["lightsOn"]); },
inactiveFunction = delegate { var e = eventCaller.currentEntity; FreezeFrame.IntroLightsSound(e.beat, e.length, e["lightsOn"]); },
defaultLength = 1f,
resizable = true,
parameters = new List<Param>()
{
new Param("lightsOn", true, "Turn Lights On", "Choose whether to turn the lights on or off."),
}
},
// settings
new GameAction("toggleOverlay", "Toggle Overlay")
{
function = delegate { var e = eventCaller.currentEntity; FreezeFrame.ToggleOverlay(e.beat, e["showOverlay"], e["showCameraMan"], e["followCamera"]); },
defaultLength = 0.5f,
parameters = new List<Param>()
{
new Param("showOverlay", true, "Show Overlay", "Choose whether or not to show the camera overlay."),
new Param("showCameraMan", true, "Show T.J.", "Choose whether or not to show the box containing T.J. Snapper."),
new Param("followCamera", true, "Follow Camera", "Choose whether or not the overlay should follow the camera."),
}
},
new GameAction("moveCameraMan", "Move T.J.")
{
function = delegate { var e = eventCaller.currentEntity; FreezeFrame.SetMoveCameraMan(e.beat, e.length, e["startPosX"], e["startPosY"], e["endPosX"], e["endPosY"], e["ease"]); },
defaultLength = 1f,
resizable = true,
parameters = new List<Param>()
{
new Param("startPosX", new EntityTypes.Float(-5.0f, 5.0f, 0.0f), "Start X Position", "X position at which to start."),
new Param("startPosY", new EntityTypes.Float(-5.0f, 5.0f, 0.0f), "Start Y Position", "Y position at which to start."),
new Param("endPosX" , new EntityTypes.Float(-5.0f, 5.0f, 0.0f), "End X Position" , "X position at which to end."),
new Param("endPosY" , new EntityTypes.Float(-5.0f, 5.0f, 0.0f), "End Y Position" , "Y position at which to end."),
new Param("ease", Util.EasingFunction.Ease.Linear, "Ease", "Set the easing of the action.", new List<Param.CollapseParam>()
{
new Param.CollapseParam((x, _) => (Util.EasingFunction.Ease)x != Util.EasingFunction.Ease.Instant, new string[] { "startPosX", "startPosY" })
}),
//new Param("flipX", false, "Flip", "Set whether or not to flip T.J. horizontally."),
}
},
new GameAction("rotateCameraMan", "Rotate T.J.")
{
function = delegate { var e = eventCaller.currentEntity; FreezeFrame.SetRotateCameraMan(e.beat, e.length, e["startRot"], e["endRot"], e["ease"]); },
defaultLength = 1f,
resizable = true,
parameters = new List<Param>()
{
new Param("startRot", new EntityTypes.Float(-360.0f, 360.0f, 0.0f), "Start Rotation", "Rotation degrees at which to start."),
new Param("endRot" , new EntityTypes.Float(-360.0f, 360.0f, 0.0f), "End Rotation" , "Rotation degrees position at which to end."),
new Param("ease", Util.EasingFunction.Ease.Linear, "Ease", "Set the easing of the action.", new List<Param.CollapseParam>()
{
new Param.CollapseParam((x, _) => (Util.EasingFunction.Ease)x != Util.EasingFunction.Ease.Instant, new string[] { "startRot" })
}),
}
},
new GameAction("scaleCameraMan", "Scale T.J.")
{
function = delegate { var e = eventCaller.currentEntity; FreezeFrame.SetScaleCameraMan(e.beat, e.length, e["startSizeX"], e["startSizeY"], e["endSizeX"], e["endSizeY"], e["ease"]); },
defaultLength = 1f,
resizable = true,
parameters = new List<Param>()
{
new Param("startSizeX", new EntityTypes.Float(-5.0f, 5.0f, 1.0f), "Start Scale X", "Horizontal scale at which to start."),
new Param("startSizeY", new EntityTypes.Float(-5.0f, 5.0f, 1.0f), "Start Scale Y", "Vertical scale at which to start."),
new Param("endSizeX", new EntityTypes.Float(-5.0f, 5.0f, 1.0f), "End Scale X" , "Horizontal scale at which to end."),
new Param("endSizeY", new EntityTypes.Float(-5.0f, 5.0f, 1.0f), "End Scale Y" , "Vertical scale at which to end."),
new Param("ease", Util.EasingFunction.Ease.Linear, "Ease", "Set the easing of the action.", new List<Param.CollapseParam>()
{
new Param.CollapseParam((x, _) => (Util.EasingFunction.Ease)x != Util.EasingFunction.Ease.Instant, new string[] { "startSizeX", "startSizeY" })
}),
}
},
},
new List<string>() { "ntr", "normal" },
"ntrcameraman", "en"
);
}
}
}
namespace HeavenStudio.Games
{
using HeavenStudio.Common;
using Scripts_FreezeFrame;
using UnityEngine.Rendering;
public class FreezeFrame : Minigame
{
/*
BIG LIST OF TODOS
- finish sounds
- wait for upscale
- make particles random sprites
- REAL icon
*/
public static FreezeFrame Instance
{
get
{
if (GameManager.instance.minigame is FreezeFrame instance)
return instance;
return null;
}
}
[SerializeField] Animator CameraMan;
[SerializeField] Photograph[] Photographs;
[SerializeField] Photograph Photograph1;
[SerializeField] Photograph Photograph2;
[SerializeField] Photograph Photograph3;
[SerializeField] Animator Results;
[SerializeField] Animator IntroSign;
[SerializeField] GameObject Overlay;
[SerializeField] GameObject Crosshair;
[SerializeField] Animator Shutter;
[SerializeField] GameObject DimRect;
[SerializeField] StickyCanvas StickyLayer;
[SerializeField] Transform FarCarSpawn;
[SerializeField] GameObject FarCarPrefab;
[SerializeField] Transform NearCarSpawn;
[SerializeField] GameObject NearCarPrefab;
[SerializeField] Transform WalkerSpawn;
[SerializeField] GameObject WalkerPrefab;
[SerializeField] Animator Crowd;
[SerializeField] SpriteRenderer CrowdFarLeft;
[SerializeField] SpriteRenderer CrowdLeft;
[SerializeField] SpriteRenderer CrowdRight;
[SerializeField] SpriteRenderer CrowdFarRight;
[SerializeField] Sprite[] CrowdSprites;
[SerializeField] GameObject Billboards;
public bool DoAutoBop { get; set; } = true;
public bool DoAutoCrosshairBlink { get; set; } = true;
public bool ShowOverlay { get; set; } = true;
public bool ShowCameraMan { get; set; } = true;
public bool OverlayFollowCamera { get; set; } = true;
public bool ShowCrowd { get; set; } = false;
public bool ShowBillboard { get; set; } = false;
public List<WalkerArgs> Walkers { get; set; } = new();
public bool SignIsMoving { get; set; } = false;
public SignMoveArgs CurrentSignArgs { get; set; }
public static Vector3 CameraManStartPos { get; private set; }
public bool CameraManMoving { get; set; } = false;
public CameraManMoveArgs CurrentCameraManMoveArgs;
public bool CameraManRotating { get; set; } = false;
public CameraManRotateArgs CurrentCameraManRotateArgs;
public bool CameraManScaling { get; set; } = false;
public CameraManScaleArgs CurrentCameraManScaleArgs;
public static List<PhotoArgs> PhotoList = new();
public Dictionary<PlayerActionEvent, PhotoArgs> EventArgs = new();
public bool IsShowingPhotos { get; set; } = false;
public List<SpawnCarArgs> QueuedCars { get; set; } = new();
public static Dictionary<RiqEntity, PersonDirection> WalkerDirections = new();
//protected static int? SuperSeed { get; set; }
// UNITY BUILTIN METHODS
void Awake()
{
CameraManStartPos = CameraMan.transform.localPosition;
//if (SuperSeed is null)
// SuperSeed = new System.Random().Next();
}
void Update()
{
if (PlayerInput.GetIsAction(InputAction_BasicPress) && !IsExpectingInputNow(InputAction_BasicPress) && !IsShowingPhotos)
{
CameraFlash();
//ScoreMiss();
}
// sign
if (SignIsMoving)
{
float normalizedBeat = conductor.GetPositionFromBeat(CurrentSignArgs.StartTime, CurrentSignArgs.Length);
Util.EasingFunction.Function func = Util.EasingFunction.GetEasingFunction(CurrentSignArgs.Ease);
float newPos = func(0f, 1f, normalizedBeat);
IntroSign.DoNormalizedAnimation(CurrentSignArgs.AnimName, newPos, animLayer: 0);
if (normalizedBeat >= 1f)
SignIsMoving = false;
}
// move TJ
if (CameraManMoving)
{
float normalizedBeat = conductor.GetPositionFromBeat(CurrentCameraManMoveArgs.StartBeat, CurrentCameraManMoveArgs.Length);
Util.EasingFunction.Function func = Util.EasingFunction.GetEasingFunction(CurrentCameraManMoveArgs.Ease);
float newPos = func(0f, 1f, normalizedBeat);
Vector3 diff = CurrentCameraManMoveArgs.EndPos - CurrentCameraManMoveArgs.StartPos;
Vector3 diffPos = newPos * diff;
CameraMan.transform.localPosition = CurrentCameraManMoveArgs.StartPos + diffPos;
if (normalizedBeat >= 1f)
{
CameraMan.transform.localPosition = CurrentCameraManMoveArgs.EndPos;
CameraManMoving = false;
}
}
if (CameraManRotating)
{
float normalizedBeat = conductor.GetPositionFromBeat(CurrentCameraManRotateArgs.StartBeat, CurrentCameraManRotateArgs.Length);
Util.EasingFunction.Function func = Util.EasingFunction.GetEasingFunction(CurrentCameraManRotateArgs.Ease);
float newPos = func(0f, 1f, normalizedBeat);
float diff = CurrentCameraManRotateArgs.EndRot - CurrentCameraManRotateArgs.StartRot;
float diffPos = newPos * diff;
CameraMan.transform.localEulerAngles = new Vector3(0, 0, CurrentCameraManRotateArgs.StartRot + diffPos);
if (normalizedBeat >= 1f)
{
CameraMan.transform.localEulerAngles = new Vector3(0, 0, CurrentCameraManRotateArgs.EndRot);
CameraManRotating = false;
}
}
if (CameraManScaling)
{
float normalizedBeat = conductor.GetPositionFromBeat(CurrentCameraManScaleArgs.StartBeat, CurrentCameraManScaleArgs.Length);
Util.EasingFunction.Function func = Util.EasingFunction.GetEasingFunction(CurrentCameraManScaleArgs.Ease);
float newPos = func(0f, 1f, normalizedBeat);
Vector3 diff = CurrentCameraManScaleArgs.EndScale - CurrentCameraManScaleArgs.StartScale;
Vector3 diffPos = newPos * diff;
CameraMan.transform.localScale = CurrentCameraManScaleArgs.StartScale + diffPos;
if (normalizedBeat >= 1f)
{
CameraMan.transform.localScale = CurrentCameraManScaleArgs.EndScale;
CameraManScaling = false;
}
}
// boppers
if (Walkers.Count > 0)
{
Walkers.RemoveAll(w => w.Walker == null || w.Walker.gameObject == null);
foreach (WalkerArgs args in Walkers)
{
float normalizedBeat = conductor.GetPositionFromBeat(args.StartTime, args.Length);
args.Walker.DoNormalizedAnimation(args.AnimName, normalizedBeat, animLayer: 1);
if (normalizedBeat >= 1f)
Destroy(args.Walker.gameObject);
}
}
// car animations
if (QueuedCars.Count > 0)
{
var beat = conductor.songPositionInBeats;
if (beat >= 0)
{
QueuedCars.RemoveAll(e => e.Beat < beat - 5); // could probably be smaller. 5 just to be safe
foreach (SpawnCarArgs args in QueuedCars.Where(e => e.Beat <= beat))
{
SpawnCar(args);
}
QueuedCars.RemoveAll(e => e.Beat <= beat);
}
}
if (!IsShowingPhotos)
Instance.Overlay.SetActive(ShowOverlay);
Billboards.SetActive(ShowBillboard);
Instance.CameraMan.gameObject.SetActive(ShowCameraMan);
StickyLayer.Sticky = OverlayFollowCamera;
}
private void OnDestroy()
{
foreach (var evt in scheduledInputs)
{
evt.Disable();
}
//if (PhotoList.Count > 0) PhotoList.Clear();
}
// MINIGAME METHODS
public override void OnBeatPulse(double beat)
{
if (BeatIsInBopRegion(beat))
{
if (DoAutoBop && !IsShowingPhotos)
Bop();
if (DoAutoCrosshairBlink)
CrosshairBlink();
}
}
public override void OnPlay(double beat)
{
if (PhotoList.Count > 0) PhotoList.Clear();
CarbageCollection();
OnGameSwitch(beat);
}
public override void OnGameSwitch(double beat)
{
Instance.Overlay.SetActive(ShowOverlay);
Instance.CameraMan.gameObject.SetActive(ShowCameraMan);
Instance.StickyLayer.Sticky = OverlayFollowCamera;
// calculation
CalculateAutoShowPhotos();
CalculateCarSpawns();
PreRandomizeWalkers();
// setting local variables
RiqEntity e = GetLastEntityOfType(beat, "bop");
if (e is not null)
{
DoAutoBop = e["autoBop"];
DoAutoCrosshairBlink = e["autoBlink"];
}
e = GetLastEntityOfType(beat, "toggleOverlay");
if (e is not null)
{
ShowOverlay = e["showOverlay"];
ShowCameraMan = e["showCameraMan"];
OverlayFollowCamera = e["followCamera"];
}
e = GetLastEntityOfType(beat, "spawnCrowd");
if (e is not null)
{
ToggleCrowd(e.beat, e["crowd"], e["customCrowd"], e["crowdFarLeft"], e["crowdLeft"], e["crowdRight"], e["crowdFarRight"], e["billboard"]);
}
// walkers
List<RiqEntity> eList = GetCurrentlyActiveEntities(beat, "spawnPerson");
if (eList.Count > 0)
{
foreach (RiqEntity entity in eList)
{
SummonWalker(entity);
}
}
// bop entities
eList = GetCurrentlyActiveEntities(beat, "bop");
if (eList.Count > 0)
{
foreach (RiqEntity entity in eList)
{
SetBopping(entity.beat, entity.length, entity["bop"], entity["autoBop"], entity["blink"], entity["autoBlink"], beat);
}
}
// Intro
e = GetLastEntityOfType(beat, "introSign");
if (e is not null)
{
DoIntroSign(e.beat, e.length, e["enter"], e["ease"]);
}
e = GetLastEntityOfType(beat, "introLights");
if (e is not null)
{
IntroLightsAnim(e.beat, e.length, e["lightsOn"]);
}
// Camera Man Movement
e = GetLastEntityOfType(beat, "moveCameraMan");
if (e is not null)
{
SetMoveCameraMan(e.beat, e.length, e["startPosX"], e["startPosY"], e["endPosX"], e["endPosY"], e["ease"]);
}
e = GetLastEntityOfType(beat, "rotateCameraMan");
if (e is not null)
{
SetRotateCameraMan(e.beat, e.length, e["startRot"], e["endRot"], e["ease"]);
}
e = GetLastEntityOfType(beat, "scaleCameraMan");
if (e is not null)
{
SetScaleCameraMan(e.beat, e.length, e["startSizeX"], e["startSizeY"], e["endSizeX"], e["endSizeY"], e["ease"]);
}
// cues
eList = GetCurrentlyActiveEntities(beat, new string[] { "slowCar", "fastCar" });
if (eList.Count > 0)
{
foreach (RiqEntity entity in eList)
{
if (beat > entity.beat + 2 || beat <= entity.beat)
continue;
if (entity.datamodel == "freezeFrame/slowCar")
{
SlowCarCue(entity.beat, entity["variant"], true);
}
if (entity.datamodel == "freezeFrame/fastCar")
{
FastCarCue(entity.beat, entity["variant"], true);
}
}
}
//if (QueuedCues.Count > 0)
//{
// QueuedCues.RemoveAll(e => e.beat < beat - 2);
// foreach (RiqEntity cue in QueuedCues)
// {
// if (cue.datamodel == "freezeFrame/slowCar")
// {
// SlowCarCue(cue.beat, cue["variant"], true);
// continue;
// }
// if (cue.datamodel == "freezeFrame/fastCar")
// {
// FastCarCue(cue.beat, cue["variant"], true);
// }
// }
//}
}
// CUE FUNCTIONS
public static void SetBopping(double beat, float length, bool bop, bool autoBop, bool blink, bool autoBlink, double currentBeat = -1)
{
if (Instance == null) return;
Instance.DoAutoBop = autoBop;
Instance.DoAutoCrosshairBlink = autoBlink;
if (bop || blink)
{
List<BeatAction.Action> actions = new List<BeatAction.Action>();
for (int i = 0; i < length; i++) {
if (beat + i < currentBeat)
continue;
if (bop)
actions.Add(new(beat + i, delegate { Instance.Bop(); }));
if (blink)
actions.Add(new(beat + i, delegate { Instance.CrosshairBlink(); }));
}
BeatAction.New(Instance, actions);
}
}
public static void SlowCarCue(double beat, int photoType, bool mute = false)
{
if (!mute) SlowCarSFX();
if (Instance == null) return;
Instance.EventArgs.Add(
Instance.ScheduleInput(beat, 2f, InputAction_BasicPress, Instance.PhotoSuccess, Instance.PhotoMiss, Instance.PhotoEmpty),
new PhotoArgs(CarType.SlowCar, (PhotoType)photoType, 0f)
);
}
public static void SlowCarSFX()
{
SoundByte.PlayOneShotGame("freezeFrame/slowCarFar", forcePlay: true);
}
public static void FastCarCue(double beat, int photoType, bool mute = false)
{
if (!mute) FastCarSFX();
if (Instance == null) return;
Instance.EventArgs.Add(
Instance.ScheduleInput(beat, 2f, InputAction_BasicPress, Instance.PhotoSuccess, Instance.PhotoMiss, Instance.PhotoEmpty),
new PhotoArgs(CarType.FastCar, (PhotoType)photoType, 0f)
);
SoundByte.PlayOneShotGame("freezeFrame/fastCarNear", beat + 2);
}
public static void FastCarSFX()
{
SoundByte.PlayOneShotGame("freezeFrame/fastCarFar", forcePlay: true);
}
public static void ShowPhotos(double beat, float length, int gradeTypeI, bool audience, bool clearCache)
{
if (Instance == null) return;
GradeType gradeType = (GradeType)gradeTypeI;
if (PhotoList.Count <= 0)
return;
SoundByte.PlayOneShotGame("freezeFrame/pictureShow");
// 2 = Hi
// 1 = OK
// 0 = Ng
int goodScore = 2;
foreach (PhotoArgs photo in PhotoList)
{
if (photo.State <= -2)
{
goodScore = 0;
break;
}
if (goodScore == 2 && photo.State != 0)
goodScore = 1;
}
if (gradeType == GradeType.Symbols)
{
switch (goodScore)
{
case 0:
Instance.Results.DoScaledAnimationAsync("Batsu", 0.5f);
break;
case 1:
Instance.Results.DoScaledAnimationAsync("Sankaku", 0.5f);
break;
case 2:
default:
Instance.Results.DoScaledAnimationAsync("Maru", 0.5f);
break;
}
}
if (gradeType == GradeType.Thumbs)
{
switch (goodScore)
{
case 0:
Instance.Results.DoScaledAnimationAsync("ThumbsDown", 0.5f);
break;
case 1:
Instance.Results.DoScaledAnimationAsync("ThumbsSide", 0.5f);
break;
case 2:
default:
Instance.Results.DoScaledAnimationAsync("ThumbsUp", 0.5f);
break;
}
}
for (int i = 0; i < PhotoList.Count && i < Instance.Photographs.Length; i++)
{
Instance.Photographs[i].ShowPhoto(PhotoList[i]);
}
if (clearCache)
PhotoList.Clear();
Instance.Overlay.SetActive(false);
Instance.DimRect.SetActive(true);
Instance.IsShowingPhotos = true;
// reactions sounds
switch (goodScore)
{
case 2:
Instance.CameraMan.DoScaledAnimationAsync("Happy", 0.5f);
SoundByte.PlayOneShotGame("freezeFrame/result_Hi");
if (audience)
break;
break;
case 1:
Instance.CameraMan.DoScaledAnimationAsync("Oops", 0.5f);
SoundByte.PlayOneShotGame("freezeFrame/result_Ok");
if (audience)
SoundByte.PlayOneShot("applause");
break;
case 0:
Instance.CameraMan.DoScaledAnimationAsync("Cry", 0.5f);
SoundByte.PlayOneShotGame("freezeFrame/result_Ng");
if (audience)
break;
break;
default:
break;
}
BeatAction.New(Instance, new List<BeatAction.Action>()
{
new BeatAction.Action(beat + length, delegate { Instance.HidePhotos(beat + length); })
});
}
public static void ClearPhotos()
{
PhotoList.Clear();
}
public static void SummonWalker(RiqEntity e/*double beat, double length, int walkerType, int direction, int layer = 0*/)
{
if (Instance == null) return;
double beat = e.beat;
double length = e.length;
PersonType walkerType = (PersonType)e["personType"];
PersonDirection direction = (PersonDirection)e["direction"];
int layer = e["layer"];
GameObject walker = Instantiate(Instance.WalkerPrefab, Instance.WalkerSpawn.transform);
Animator animator = walker.GetComponent<Animator>();
walker.GetComponent<SortingGroup>().sortingOrder = layer;
switch (walkerType)
{
case PersonType.Girlfriend:
animator.DoScaledAnimationAsync("Girlfriend", animLayer: 2);
break;
case PersonType.Dude2:
animator.DoScaledAnimationAsync("Dude2", animLayer: 2);
break;
case PersonType.Dude1:
default:
animator.DoScaledAnimationAsync("Dude1", animLayer: 2);
break;
}
/*if (direction == (int)PersonDirection.Random)
{
int seed = BitConverter.ToInt32(BitConverter.GetBytes((float)beat));
direction = new System.Random(seed).Next(1, 3);
}*/
if (direction == PersonDirection.Random)
{
if (WalkerDirections.ContainsKey(e))
direction = WalkerDirections[e];
else
direction = PersonDirection.Right;
}
if (direction == PersonDirection.Left)
Instance.Walkers.Add(new WalkerArgs(animator, beat, length, "EnterLeft"));
else
Instance.Walkers.Add(new WalkerArgs(animator, beat, length, "EnterRight"));
double nextBeat = Math.Ceiling(beat);
List<BeatAction.Action> actions = new();
for (double i = nextBeat; i < beat + length; i += 1)
{
actions.Add(new(i, delegate { animator.DoScaledAnimationAsync("Bop", timeScale: 0.5f, animLayer: 0); }));
}
BeatAction.New(Instance, actions);
}
public static void ToggleCrowd(double beat, bool showCrowd, bool customCrowd, int crowdFarLeft, int crowdLeft, int crowdRight, int crowdFarRight, bool billboard)
{
if (Instance == null) return;
Instance.ShowCrowd = showCrowd;
if (Instance.ShowCrowd)
Instance.Crowd.DoScaledAnimationAsync("Show", 0.5f);
else
Instance.Crowd.DoScaledAnimationAsync("Hide", 0.5f);
if (customCrowd)
{
Instance.CrowdFarLeft.sprite = Instance.CrowdSprites[crowdFarLeft];
Instance.CrowdLeft.sprite = Instance.CrowdSprites[crowdLeft];
Instance.CrowdRight.sprite = Instance.CrowdSprites[crowdRight];
Instance.CrowdFarRight.sprite = Instance.CrowdSprites[crowdFarRight];
}
else
{
Instance.CrowdFarLeft.sprite = Instance.CrowdSprites[2];
Instance.CrowdLeft.sprite = Instance.CrowdSprites[1];
Instance.CrowdRight.sprite = Instance.CrowdSprites[0];
Instance.CrowdFarRight.sprite = Instance.CrowdSprites[2];
}
Instance.ShowBillboard = billboard;
}
public static void DoIntroSign(double beat, double length, bool enter, int easeIndex)
{
Util.EasingFunction.Ease ease = (Util.EasingFunction.Ease)easeIndex;
Instance.SignIsMoving = true;
if (enter)
Instance.CurrentSignArgs = new("Enter", beat, length, ease);
else
Instance.CurrentSignArgs = new("Exit", beat, length, ease);
}
public static void IntroLightsAnim(double beat, double length, bool lightsOn)
{
if (!lightsOn)
{
Instance.IntroSign.DoScaledAnimationAsync("LightsOff", timeScale: 0.5f, animLayer: 1);
return;
}
Instance.IntroSign.DoScaledAnimationFromBeatAsync("Light01", startBeat: beat, timeScale: 0.5f, animLayer: 1);
BeatAction.New(Instance, new List<BeatAction.Action>
{
new(beat + length, delegate { Instance.IntroSign.DoScaledAnimationFromBeatAsync("Light02", startBeat: beat + length, timeScale: 0.5f, animLayer: 1); }),
new(beat + (length * 2), delegate { Instance.IntroSign.DoScaledAnimationFromBeatAsync("Light03", startBeat: beat + (length * 2), timeScale: 0.5f, animLayer: 1); }),
}
);
}
public static void IntroLightsSound(double beat, double length, bool lightsOn)
{
if (!lightsOn)
return;
SoundByte.PlayOneShotGame("freezeFrame/beginningSignal1", forcePlay: true);
MultiSound.Play(new MultiSound.Sound[] {
new MultiSound.Sound("freezeFrame/beginningSignal1", beat + length),
new MultiSound.Sound("freezeFrame/beginningSignal2", beat + (length * 2)),
}, forcePlay: true);
}
public static void ToggleOverlay(double beat, bool showOverlay, bool showCameraMan, bool followCamera)
{
Instance.ShowOverlay = showOverlay;
Instance.ShowCameraMan = showCameraMan;
Instance.OverlayFollowCamera = followCamera;
}
public static void SetMoveCameraMan(double beat, double length, float startX, float startY, float endX, float endY, int easeIndex)
{
Instance.CurrentCameraManMoveArgs = new(
beat,
length,
new Vector3(startX, startY, 0) + CameraManStartPos,
new Vector3(endX, endY, 0) + CameraManStartPos,
(Util.EasingFunction.Ease)easeIndex
);
Instance.CameraManMoving = true;
}
public static void SetRotateCameraMan(double beat, double length, float startRot, float endRot, int easeIndex)
{
Instance.CurrentCameraManRotateArgs = new(
beat,
length,
startRot,
endRot,
(Util.EasingFunction.Ease)easeIndex
);
Instance.CameraManRotating = true;
}
public static void SetScaleCameraMan(double beat, double length, float startX, float startY, float endX, float endY, int easeIndex)
{
Instance.CurrentCameraManScaleArgs = new(
beat,
length,
new Vector3(startX, startY, 1),
new Vector3(endX, endY, 1),
(Util.EasingFunction.Ease)easeIndex
);
Instance.CameraManScaling = true;
}
// PRE-FUNCTIONS
public void SpawnCar(SpawnCarArgs args)
{
if (args.Near)
{
if (NearCarSpawn == null)
{
UnityEngine.Debug.LogError($"Failed to spawn a car at beat {args.Beat}.");
return;
}
Animator car = Instantiate(NearCarPrefab, NearCarSpawn).GetComponent<Animator>();
car.DoScaledAnimationFromBeatAsync("Idle", startBeat: 0f, timeScale: 0.5f, animLayer: 0);
if (args.Fast)
car.DoScaledAnimationFromBeatAsync("FastCarGo", startBeat: args.Beat, timeScale: 2.666666666666667f, animLayer: 1);
else
car.DoScaledAnimationFromBeatAsync("SlowCarGo", startBeat: args.Beat, timeScale: 1.5f, animLayer: 1);
//BeatAction.New(Instance, new List<BeatAction.Action>() { new BeatAction.Action(args.Beat + 3, delegate { Destroy(car); }) });
}
else
{
if (FarCarSpawn == null)
{
UnityEngine.Debug.LogError($"Failed to spawn a car at beat {args.Beat}.");
return;
}
Animator car = Instantiate(FarCarPrefab, FarCarSpawn).GetComponent<Animator>();
car.DoScaledAnimationFromBeatAsync("Idle", startBeat: 0f, timeScale: 0.5f, animLayer: 0);
if (args.Fast)
car.DoScaledAnimationFromBeatAsync("FastCarGo", startBeat: args.Beat, timeScale: 0.5f, animLayer: 1);
else
car.DoScaledAnimationFromBeatAsync("SlowCarGo", startBeat: args.Beat, timeScale: 0.16666666666666666666666666666667f, animLayer: 1);
//BeatAction.New(Instance, new List<BeatAction.Action>() { new BeatAction.Action(args.Beat + 8, delegate { Destroy(car); }) });
}
}
/*public void SpawnSlowCarNear(double beat)
{
if (NearCarSpawn == null) return;
Animator nearCar = Instantiate(NearCarPrefab, NearCarSpawn).GetComponent<Animator>();
nearCar.DoScaledAnimationFromBeatAsync("Idle", startBeat: 0f, timeScale: 0.5f, animLayer: 0);
double startBeat = beat + 2 - 0.16666666666666666666666666666667;
BeatAction.New(Instance, new List<BeatAction.Action>()
{
new BeatAction.Action(startBeat, delegate { nearCar.DoScaledAnimationFromBeatAsync("SlowCarGo", startBeat: startBeat, timeScale: 1.5f, animLayer: 1); }),
new BeatAction.Action(beat + 3, delegate { Destroy(nearCar); } )
});
}
public void SpawnSlowCarFar(double beat)
{
//if (beat < 0) return;
if (FarCarSpawn == null) return;
Animator farCar = Instantiate(FarCarPrefab, FarCarSpawn).GetComponent<Animator>();
farCar.DoScaledAnimationFromBeatAsync("Idle", startBeat: 0f, timeScale: 0.5f, animLayer: 0);
farCar.DoScaledAnimationFromBeatAsync("SlowCarGo", startBeat: beat, timeScale: 0.16666666666666666666666666666667f, animLayer: 1);
BeatAction.New(Instance, new List<BeatAction.Action>()
{
new BeatAction.Action(beat + 7, delegate { Destroy(farCar); } )
});
}
public void SpawnFastCar(double beat)
{
if (FarCarSpawn != null)
{
UnityEngine.Debug.Log("farcar");
Animator farCar = Instantiate(FarCarPrefab, FarCarSpawn).GetComponent<Animator>();
farCar.DoScaledAnimationFromBeatAsync("Idle", startBeat: 0f, timeScale: 0.5f, animLayer: 0);
BeatAction.New(Instance, new List<BeatAction.Action>()
{
new BeatAction.Action(beat - 0.5, delegate { if (beat >= 0.5) farCar.DoScaledAnimationFromBeatAsync("FastCarGo", startBeat: beat - 0.5, timeScale: 0.5f, animLayer: 1); }),
new BeatAction.Action(beat + 3, delegate { Destroy(farCar); } )
});
}
if (NearCarSpawn != null)
{
UnityEngine.Debug.Log("fartcar");
Animator nearCar = Instantiate(NearCarPrefab, NearCarSpawn).GetComponent<Animator>();
nearCar.DoScaledAnimationFromBeatAsync("Idle", startBeat: 0f, timeScale: 0.5f, animLayer: 0);
BeatAction.New(Instance, new List<BeatAction.Action>()
{
new BeatAction.Action(beat + 2 - 0.09375, delegate { nearCar.DoScaledAnimationFromBeatAsync("FastCarGo", startBeat: beat - 0.09375, timeScale: 2.666666666666667f, animLayer: 1); }),
new BeatAction.Action(beat + 3, delegate { Destroy(nearCar); } )
});
}
}*/
// INPUT RESULTS
public void PhotoSuccess(PlayerActionEvent caller, float state)
{
PhotoArgs args;
bool hasArgs = EventArgs.TryGetValue(caller, out args);
EventArgs.Remove(caller);
// passing the args for the photos
if (hasArgs)
{
if (state >= 1f)
{
args.State = 1;
}
else if (state <= -1f)
{
args.State = -1;
}
else
{
args.State = 0;
}
PushPhoto(args);
}
CameraFlash();
}
public void PhotoMiss(PlayerActionEvent caller)
{
PhotoArgs args;
bool hasArgs = EventArgs.TryGetValue(caller, out args);
EventArgs.Remove(caller);
if (hasArgs)
{
args.State = -2;
PushPhoto(args);
}
}
public void PhotoEmpty(PlayerActionEvent caller)
{
}
// GENERAL METHODS
public void Bop()
{
CameraMan.DoScaledAnimationAsync("Bop", 0.5f);
}
public void CrosshairBlink()
{
Crosshair.SetActive(!Crosshair.activeSelf);
}
public void CameraFlash()
{
Shutter.DoScaledAnimationAsync("Shut", 0.5f);
CameraMan.DoScaledAnimationAsync("Flash", 0.5f);
SoundByte.PlayOneShotGame("freezeFrame/shutter"/*, pitch: (float)new System.Random().NextDouble() + 0.5f*/);
}
public void PushPhoto(PhotoArgs args)
{
//while (PhotoList.Count >= MAX_PHOTOS)
// PhotoList.RemoveAt(0);
if (args.PhotoType == PhotoType.Random)
{
if (UnityEngine.Random.Range(0, 8) >= 7)
{
switch (UnityEngine.Random.Range(0, 3))
{
case 0:
args.PhotoType = PhotoType.Ninja;
break;
case 1:
args.PhotoType = PhotoType.Ghost;
break;
case 2:
args.PhotoType = PhotoType.Rats;
break;
default:
args.PhotoType = PhotoType.Default;
break;
}
}
else
args.PhotoType = PhotoType.Default;
}
PhotoList.Add(args);
}
public void HidePhotos(double beat)
{
Overlay.SetActive(ShowOverlay);
DimRect.SetActive(false);
foreach (Photograph photo in Photographs)
photo.HideAll();
Results.DoScaledAnimationAsync("None", 0.5f);
IsShowingPhotos = false;
if (beat % 1 == 0 && DoAutoBop)
CameraMan.DoScaledAnimationAsync("Bop", 0.5f);
else
CameraMan.DoScaledAnimationAsync("Idle", 0.5f);
}
/*public static void QueueCue(RiqEntity e)
{
if (e.datamodel == "freezeFrame/slowCar")
{
SoundByte.PlayOneShotGame("freezeFrame/smallCarZoom1a", forcePlay: true);
}
if (e.datamodel == "freezeFrame/fastCar")
{
SoundByte.PlayOneShotGame("freezeFrame/fastCarZoom", forcePlay: true);
}
QueuedCues.Add(e);
}*/
public void CalculateAutoShowPhotos()
{
List<RiqEntity> allCars = EventCaller.GetAllInGameManagerList("freezeFrame", new string[] { "slowCar", "fastCar" });
List<BeatAction.Action> actions = new();
List<double> beats = new(); // so you don't double up
foreach (RiqEntity entity in allCars.Where(car => (bool)car["autoShowPhotos"]))
{
double showBeat = 3f;
if (allCars.Any(car => car.beat == entity.beat - 1f))
showBeat = 3.5f;
if (entity.datamodel == "freezeFrame/fastCar")
showBeat = 4f;
if (allCars.Any(car => car.beat == entity.beat - 2f))
showBeat = 4.5f;
showBeat = entity.beat + showBeat;
if (!allCars.Any(car => car.beat > entity.beat && car.beat <= showBeat))
{
if (!beats.Any(b => showBeat >= b && showBeat < b + 2))
{
beats.Add(showBeat);
actions.Add(new BeatAction.Action(showBeat, delegate { ShowPhotos(showBeat, 2, (int)entity["gradeType"], (bool)entity["audience"], false); }));
}
}
}
if (actions.Count > 0)
{
BeatAction.New(Instance, actions);
}
}
public void CalculateCarSpawns()
{
List<RiqEntity> fastCars = EventCaller.GetAllInGameManagerList("freezeFrame", new string[] { "fastCar" });
foreach (RiqEntity e in fastCars)
{
QueuedCars.Add(new SpawnCarArgs(e.beat - 0.5, true, false));
QueuedCars.Add(new SpawnCarArgs(e.beat + 2 - 0.09375, true, true));
}
List<RiqEntity> slowCars = EventCaller.GetAllInGameManagerList("freezeFrame", new string[] { "slowCar" });
foreach (RiqEntity e in slowCars)
{
QueuedCars.Add(new SpawnCarArgs(e.beat + 2 - 0.16666666666666666666666666666667, false, true));
}
List<List<double>> clusters = new();
while (slowCars.Count > 0)
{
double minBeat = slowCars[0].beat;
double maxBeat = minBeat + 2;
clusters.Add(slowCars.Where(car => car.beat >= minBeat && car.beat < maxBeat).Select(car => car.beat).ToList());
slowCars.RemoveAll(car => car.beat >= minBeat && car.beat < maxBeat);
}
foreach (List<double> cluster in clusters)
{
double midBeat = cluster.Min() + ((cluster.Max() - cluster.Min()) / 2);
foreach (double beat in cluster)
{
double diff = midBeat - beat;
double modifiedBeat = midBeat + (diff / 4);
//BeatAction.New(Instance, new List<BeatAction.Action>(){
// new BeatAction.Action(modifiedBeat - 4, delegate { SpawnSlowCarFar(modifiedBeat - 4); } )
//});
QueuedCars.Add(new SpawnCarArgs(modifiedBeat - 4, false, false));
}
}
}
public void PreRandomizeWalkers()
{
IEnumerable<RiqEntity> walkers = EventCaller.GetAllInGameManagerList("freezeFrame", new string[] { "spawnPerson" }).Where(e => (PersonDirection)e["direction"] == PersonDirection.Random);
foreach (RiqEntity e in walkers)
{
if (!WalkerDirections.ContainsKey(e))
{
float rand = UnityEngine.Random.Range(0.0f, 1.0f);
if (rand >= 0.5)
{
WalkerDirections.Add(e, PersonDirection.Left);
}
else
{
WalkerDirections.Add(e, PersonDirection.Right);
}
}
}
List<RiqEntity> keysToRemove = new();
foreach (RiqEntity key in WalkerDirections.Keys)
{
if (!walkers.Contains(key))
keysToRemove.Add(key);
}
foreach (RiqEntity key in keysToRemove)
{
WalkerDirections.Remove(key);
}
Debug.Log($"Walker Count: {WalkerDirections.Count}");
}
public void CarbageCollection()
{
foreach (Transform child in FarCarSpawn)
{
Destroy(child.gameObject);
}
foreach (Transform child in NearCarSpawn)
{
Destroy(child.gameObject);
}
foreach (Transform child in WalkerSpawn)
{
Destroy(child.gameObject);
}
}
public RiqEntity GetLastEntityOfType(double beat, string datamodel)
{
foreach (RiqEntity e in EventCaller.GetAllInGameManagerList("freezeFrame", new string[] { datamodel }).OrderBy(e => -e.beat))
{
if (e.beat < beat)
return e;
}
return null;
}
public List<RiqEntity> GetCurrentlyActiveEntities(double beat, string datamodel)
{
return GetCurrentlyActiveEntities(beat, new string[] { datamodel });
}
public List<RiqEntity> GetCurrentlyActiveEntities(double beat, string[] datamodel)
{
List<RiqEntity> result = new();
foreach (RiqEntity e in EventCaller.GetAllInGameManagerList("freezeFrame", datamodel))
{
if (beat >= e.beat && beat <= e.beat + e.length)
result.Add(e);
if (e.beat > beat)
break;
}
return result;
}
/*protected static System.Random GetSeededRandom(float? mulch = null) // i just made this term up i have no idea if it has any basis in actual programming
{
if (SuperSeed is null)
SuperSeed = new System.Random().Next();
if (mulch is not null)
{
int seed = BitConverter.ToInt32(BitConverter.GetBytes(mulch.Value));
return new System.Random(SuperSeed.Value * seed);
}
return new System.Random(SuperSeed.Value);
}*/
// ENUMS
public enum CarType : int
{
SlowCar = 0,
FastCar = 1
}
public enum PhotoType : int
{
Random = 0,
Default = 1,
Ninja = 2,
Ghost = 3,
Rats = 4,
PeaceSign = 5,
GirlfriendRight = 6,
GirlfriendLeft = 7,
Dude1Right = 8,
Dude1Left = 9,
Dude2Right = 10,
Dude2Left = 11,
}
public enum PersonType : int
{
Dude1 = 0,
Dude2 = 1,
Girlfriend = 2
}
public enum PersonDirection : int
{
Random = 0,
Right = 1,
Left = 2
}
public enum GradeType : int
{
Symbols = 0,
Thumbs = 1,
None = 2
}
public enum CustomCrowdType : int
{
TealDancers = 0,
YellowDancers = 1,
PinkDancers = 2,
CyanDancers = 3,
}
// STRUCTS
public struct PhotoArgs
{
public CarType Car;
public PhotoType PhotoType;
public float State;
public PhotoArgs(CarType car, PhotoType photoType, float state)
{
Car = car;
PhotoType = photoType;
State = state;
}
}
public struct WalkerArgs
{
public Animator Walker;
public double StartTime;
public double Length;
public string AnimName;
public WalkerArgs(Animator walker, double startTime, double length, string animName)
{
Walker = walker;
StartTime = startTime;
Length = length;
AnimName = animName;
}
}
public struct SignMoveArgs
{
public string AnimName;
public double StartTime;
public double Length;
public Util.EasingFunction.Ease Ease;
public SignMoveArgs(string animName, double startTime, double length, Util.EasingFunction.Ease ease)
{
AnimName = animName;
StartTime = startTime;
Length = length;
Ease = ease;
}
}
public struct CameraManMoveArgs
{
public double StartBeat;
public double Length;
public Vector3 StartPos;
public Vector3 EndPos;
public Util.EasingFunction.Ease Ease;
public CameraManMoveArgs(double startBeat, double length, Vector3 startPos, Vector3 endPos, Util.EasingFunction.Ease ease)
{
StartBeat = startBeat;
Length = length;
StartPos = startPos;
EndPos = endPos;
Ease = ease;
}
}
public struct CameraManRotateArgs
{
public double StartBeat;
public double Length;
public float StartRot;
public float EndRot;
public Util.EasingFunction.Ease Ease;
public CameraManRotateArgs(double startBeat, double length, float startRot, float endRot, Util.EasingFunction.Ease ease)
{
StartBeat = startBeat;
Length = length;
StartRot = startRot;
EndRot = endRot;
Ease = ease;
}
}
public struct CameraManScaleArgs
{
public double StartBeat;
public double Length;
public Vector3 StartScale;
public Vector3 EndScale;
public Util.EasingFunction.Ease Ease;
public CameraManScaleArgs(double startBeat, double length, Vector3 startScale, Vector3 endScale, Util.EasingFunction.Ease ease)
{
StartBeat = startBeat;
Length = length;
StartScale = startScale;
EndScale = endScale;
Ease = ease;
}
}
public struct SpawnCarArgs
{
public double Beat;
public bool Near;
public bool Fast;
public SpawnCarArgs(double beat, bool fast, bool near)
{
Beat = beat;
Near = near;
Fast = fast;
}
}
}
}