HeavenStudio/Assets/Scripts/Games/DoubleDate/DoubleDate.cs
minenice55 2272416fa7
Double Date Balls (#396)
* al l anims done yay

* make balls follow paths

added FollowPath objects

* added 2 grass and changed sky

* make balls rotate

todo: shadows

* complete SuperCurve

add dropshadows
add weasel hit

* make football stop dropshadow when hit

* finish animation

add scrolling clouds

* tint shader

* oops

* slow down clouds

---------

Co-authored-by: ev <85412919+evdial@users.noreply.github.com>
2023-04-22 19:20:01 +00:00

343 lines
11 KiB
C#

using HeavenStudio.Util;
using System;
using System.Collections.Generic;
using UnityEngine;
namespace HeavenStudio.Games.Loaders
{
using static Minigames;
public static class RvlDoubleDateLoader
{
public static Minigame AddGame(EventCaller eventCaller) {
return new Minigame("doubleDate", "Double Date", "ef854a", false, false, new List<GameAction>()
{
new GameAction("bop", "Bop")
{
function = delegate { var e = eventCaller.currentEntity; DoubleDate.instance.Bop(e.beat, e.length, e["bop"], e["autoBop"]); },
resizable = true,
parameters = new List<Param>()
{
new Param("bop", true, "Bop", "Should the two couples bop?"),
new Param("autoBop", false, "Bop (Auto)", "Should the two couples auto bop?")
}
},
new GameAction("soccer", "Soccer Ball")
{
preFunction = delegate { var e = eventCaller.currentEntity; DoubleDate.QueueSoccerBall(e.beat); },
defaultLength = 2f,
},
new GameAction("basket", "Basket Ball")
{
preFunction = delegate { var e = eventCaller.currentEntity; DoubleDate.QueueBasketBall(e.beat); },
defaultLength = 2f,
},
new GameAction("football", "Football")
{
preFunction = delegate { var e = eventCaller.currentEntity; DoubleDate.QueueFootBall(e.beat); },
defaultLength = 2.5f,
},
});
}
}
}
namespace HeavenStudio.Games
{
using Scripts_DoubleDate;
public class DoubleDate : Minigame
{
[Header("Prefabs")]
[SerializeField] GameObject soccer;
[SerializeField] GameObject basket;
[SerializeField] GameObject football;
[SerializeField] GameObject dropShadow;
[SerializeField] ParticleSystem leaves;
[Header("Components")]
[SerializeField] Animator boyAnim;
[SerializeField] Animator girlAnim;
[SerializeField] DoubleDateWeasels weasels;
[SerializeField] Animator treeAnim;
[SerializeField] GameObject clouds;
[Header("Variables")]
[SerializeField] public float cloudSpeed;
[SerializeField] public float cloudDistance;
[SerializeField] public float floorHeight;
[SerializeField] public float shadowDepthScaleMin;
[SerializeField] public float shadowDepthScaleMax;
[SerializeField] SuperCurveObject.Path[] ballBouncePaths;
float lastGirlGacha = float.MinValue;
bool shouldBop = true;
bool canBop = true;
GameEvent bop = new GameEvent();
public static DoubleDate instance;
public static List<QueuedBall> queuedBalls = new List<QueuedBall>();
[NonSerialized] public float lastHitWeasel = float.MinValue;
public enum BallType
{
Soccer,
Basket,
Football
}
public struct QueuedBall
{
public float beat;
public BallType type;
}
// Editor gizmo to draw trajectories
new void OnDrawGizmos()
{
base.OnDrawGizmos();
foreach (SuperCurveObject.Path path in ballBouncePaths)
{
if (path.preview)
{
soccer.GetComponent<SoccerBall>().DrawEditorGizmo(path);
}
}
}
public override void OnPlay(float beat)
{
queuedBalls.Clear();
}
private void Awake()
{
instance = this;
}
private void Start() {
clouds.transform.position = Vector3.left * ((Time.realtimeSinceStartup * cloudSpeed) % cloudDistance);
}
void Update()
{
var cond = Conductor.instance;
if (cond.isPlaying && !cond.isPaused)
{
if (queuedBalls.Count != 0)
{
foreach (QueuedBall ball in queuedBalls)
{
switch (ball.type)
{
case BallType.Soccer:
SpawnSoccerBall(ball.beat);
break;
case BallType.Basket:
SpawnBasketBall(ball.beat);
break;
case BallType.Football:
SpawnFootBall(ball.beat);
break;
}
}
queuedBalls.Clear();
}
if (cond.ReportBeat(ref bop.lastReportedBeat, bop.startBeat % 1) && shouldBop)
{
SingleBop();
}
}
else
{
if ((!cond.isPaused) && queuedBalls.Count != 0)
{
queuedBalls.Clear();
}
}
if (PlayerInput.Pressed() && !IsExpectingInputNow(InputType.STANDARD_DOWN))
{
Jukebox.PlayOneShotGame("doubleDate/kick_whiff");
Kick(true, true, false);
}
clouds.transform.position = Vector3.left * ((Time.realtimeSinceStartup * cloudSpeed) % cloudDistance);
}
public void ToggleBop(bool go)
{
canBop = go;
}
public void Bop(float beat, float length, bool goBop, bool autoBop)
{
shouldBop = autoBop;
if (goBop)
{
for (int i = 0; i < length; i++)
{
BeatAction.New(instance.gameObject, new List<BeatAction.Action>()
{
new BeatAction.Action(beat + i, delegate { SingleBop(); })
});
}
}
}
void SingleBop()
{
if (canBop)
{
boyAnim.DoScaledAnimationAsync("IdleBop", 1f);
}
if (Conductor.instance.songPositionInBeats > lastGirlGacha)
girlAnim.DoScaledAnimationAsync("GirlBop", 1f);
weasels.Bop();
}
public void Kick(bool hit = true, bool forceNoLeaves = false, bool weaselsHappy = true, bool jump = false)
{
if (hit)
{
boyAnim.DoScaledAnimationAsync("Kick", 0.5f);
if (jump)
{
weasels.Jump();
lastGirlGacha = Conductor.instance.songPositionInBeats + 0.5f;
girlAnim.DoScaledAnimationAsync("GirlLookUp", 0.5f);
}
else if (weaselsHappy) weasels.Happy();
if (!forceNoLeaves)
{
BeatAction.New(instance.gameObject, new List<BeatAction.Action>()
{
new BeatAction.Action(Conductor.instance.songPositionInBeats + 1f, delegate
{
leaves.Play();
treeAnim.DoScaledAnimationAsync("TreeRustle", 1f);
})
});
}
}
else
{
boyAnim.DoScaledAnimationAsync("Barely", 0.5f);
weasels.Surprise();
}
}
public static void QueueSoccerBall(float beat)
{
if (instance == null)
{
queuedBalls.Add(new QueuedBall()
{
beat = beat,
type = BallType.Soccer
});
}
else
{
instance.SpawnSoccerBall(beat);
}
Jukebox.PlayOneShotGame("doubleDate/soccerBounce", beat, forcePlay: true);
}
public static void QueueBasketBall(float beat)
{
if (instance == null)
{
queuedBalls.Add(new QueuedBall()
{
beat = beat,
type = BallType.Basket
});
}
else
{
instance.SpawnBasketBall(beat);
}
MultiSound.Play(new MultiSound.Sound[]
{
new MultiSound.Sound("doubleDate/basketballBounce", beat),
new MultiSound.Sound("doubleDate/basketballBounce", beat + 0.75f),
});
}
public static void QueueFootBall(float beat)
{
if (instance == null)
{
queuedBalls.Add(new QueuedBall()
{
beat = beat,
type = BallType.Football
});
}
else
{
instance.SpawnFootBall(beat);
}
MultiSound.Play(new MultiSound.Sound[]
{
new MultiSound.Sound("doubleDate/footballBounce", beat),
new MultiSound.Sound("doubleDate/footballBounce", beat + 0.75f),
});
}
public void SpawnSoccerBall(float beat)
{
SoccerBall spawnedBall = Instantiate(soccer, instance.transform).GetComponent<SoccerBall>();
spawnedBall.Init(beat);
}
public void SpawnBasketBall(float beat)
{
Basketball spawnedBall = Instantiate(basket, instance.transform).GetComponent<Basketball>();
spawnedBall.Init(beat);
}
public void SpawnFootBall(float beat)
{
Football spawnedBall = Instantiate(football, instance.transform).GetComponent<Football>();
spawnedBall.Init(beat);
}
public void MissKick(float beat, bool hit = false)
{
lastGirlGacha = Conductor.instance.songPositionInBeats + 1.5f;
girlAnim.DoScaledAnimationAsync("GirlSad", 0.5f);
if (hit)
{
lastHitWeasel = Conductor.instance.songPositionInBeats;
BeatAction.New(gameObject, new List<BeatAction.Action>()
{
new BeatAction.Action(beat - (0.25f/3f), delegate { weasels.Hit(beat); }),
});
}
else
{
lastHitWeasel = Conductor.instance.songPositionInBeats;
BeatAction.New(gameObject, new List<BeatAction.Action>()
{
new BeatAction.Action(beat + 0.25, delegate { weasels.Hide(beat + 0.25f); }),
});
}
}
public SuperCurveObject.Path GetPath(string name)
{
foreach (SuperCurveObject.Path path in ballBouncePaths)
{
if (path.name == name)
{
Debug.Log("Found path " + name);
return path;
}
}
return default(SuperCurveObject.Path);
}
public GameObject MakeDropShadow()
{
GameObject shadow = Instantiate(dropShadow, transform);
return shadow;
}
}
}