HeavenStudioPlus/Assets/Scripts/Games/SpaceSoccer/Ball.cs
Zeo 3a4279ce5e 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

282 lines
No EOL
14 KiB
C#

using System;
using UnityEngine;
using HeavenStudio.Util;
namespace HeavenStudio.Games.Scripts_SpaceSoccer
{
public class Ball : SuperCurveObject
{
public enum State { None, Dispensing, Kicked, HighKicked, Toe };
[Header("Components")]
[HideInInspector] public Kicker kicker;
[SerializeField] private GameObject holder;
[SerializeField] private GameObject spriteHolder;
[Space(10)]
//[SerializeField] private BezierCurve3D dispenseCurve;
//[SerializeField] private BezierCurve3D kickCurve;
//[SerializeField] private BezierCurve3D highKickCurve;
//[SerializeField] private BezierCurve3D toeCurve;
[Header("Properties")]
public double startBeat;
public State state;
public double nextAnimBeat;
public float highKickSwing = 0f;
private float lastSpriteRot;
public bool canKick;
public bool waitKickRelease;
private bool lastKickLeft;
private SuperCurveObject.Path kickPath;
private SuperCurveObject.Path dispensePath;
private SuperCurveObject.Path highKickPath;
private SuperCurveObject.Path toePath;
//private float currentKickPathScale = 1;
protected override void UpdateLastRealPos()
{
lastRealPos = transform.localPosition;
}
public void Init(Kicker kicker, double dispensedBeat)
{
this.kicker = kicker;
kicker.ball = this;
kicker.dispenserBeat = dispensedBeat;
double currentBeat = Conductor.instance.songPositionInBeatsAsDouble;
kickPath = SpaceSoccer.instance.GetPath("Kick");
dispensePath = SpaceSoccer.instance.GetPath("Dispense");
highKickPath = SpaceSoccer.instance.GetPath("HighKick");
toePath = SpaceSoccer.instance.GetPath("Toe");
//holder.transform.localPosition = kicker.transform.GetChild(0).position;
if (currentBeat - dispensedBeat < 2f) //check if ball is currently being dispensed (should only be false if starting in the middle of the remix)
{
//Debug.Log("Dispensing");
state = State.Dispensing;
startBeat = dispensedBeat;
nextAnimBeat = startBeat + GetAnimLength(State.Dispensing);
kicker.kickTimes = 0;
return;
}
var highKicks = GameManager.instance.Beatmap.Entities.FindAll(c => c.datamodel == "spaceSoccer/high kick-toe!");
int numHighKicks = 0;
//determine what state the ball was in for the previous kick.
for(int i = 0; i < highKicks.Count; i++)
{
if (highKicks[i].beat + highKicks[i].length <= currentBeat)
{
numHighKicks++;
continue;
}
if (highKicks[i].beat > currentBeat)
{
//Debug.Log("Setting state to kicked");
state = State.Kicked;
double relativeBeat = currentBeat - dispensedBeat;
startBeat = dispensedBeat + (int)(relativeBeat - 0.1); //this makes the startBeat be for the kick that is currently in progress, but it won't play the kicker's animation for that kick. the -0.1 makes it so that if playback is started right when the kicker kicks, it still plays the kicker's animation.
nextAnimBeat = startBeat + GetAnimLength(State.Kicked);
kicker.kickTimes = (int)(relativeBeat - 0.1) - numHighKicks - 1; //every high kick has 2 kicks in the same time a regular keep-up does 3 kicks.
break;
}
else
{
highKickSwing = 0.5f;
if (highKicks[i].beat + GetAnimLength(State.HighKicked) > currentBeat)
{
//Debug.Log("Setting state to high kick");
state = State.HighKicked;
double relativeBeat = highKicks[i].beat - dispensedBeat;
startBeat = dispensedBeat + Math.Ceiling(relativeBeat); //there is a chance this makes startBeat later than the current beat, but it shouldn't matter too much. It would only happen if the user places the high kicks incorrectly.
nextAnimBeat = startBeat + GetAnimLength(State.HighKicked);
kicker.kickTimes = (int)Math.Ceiling(relativeBeat) - numHighKicks - 1;
break;
}
else
{
//Debug.Log("Setting state to toe");
state = State.Toe;
double relativeBeat = Math.Ceiling(highKicks[i].beat - dispensedBeat) + GetAnimLength(State.HighKicked); //there is a chance this makes startBeat later than the current beat, but it shouldn't matter too much. It would only happen if the user places the high kicks incorrectly.
startBeat = dispensedBeat + relativeBeat;
nextAnimBeat = startBeat + GetAnimLength(State.Toe);
kicker.kickTimes = (int)(relativeBeat - GetAnimLength(State.HighKicked)) - numHighKicks;
break;
}
}
}
if(state == 0) //if the for loop didn't set the state, i.e. all the high kicks happen before the point we start at.
{
//Debug.Log("Defaulting to kicked state");
state = State.Kicked;
double relativeBeat = currentBeat - dispensedBeat;
startBeat = dispensedBeat + (int)(relativeBeat - 0.1); //this makes the startBeat be for the kick that is currently in progress, but it won't play the kicker's animation for that kick. the -0.1 makes it so that if playback is started right when the kicker kicks, it still plays the kicker's animation.
nextAnimBeat = startBeat + GetAnimLength(State.Kicked);
kicker.kickTimes = (int)(relativeBeat - 0.1) - numHighKicks - 1;
}
Update(); //make sure the ball is in the right place
}
public void Kick(bool player)
{
if (player)
SoundByte.PlayOneShotGame("spaceSoccer/ballHit", -1, SoundByte.GetPitchFromCents(UnityEngine.Random.Range(-38, 39), false));
lastSpriteRot = spriteHolder.transform.eulerAngles.z;
SetState(State.Kicked);
lastKickLeft = kicker.kickLeft;
/*if (kicker.kickLeft)
{
kickCurve.transform.localScale = new Vector3(-1, 1);
currentKickPathScale = -1;
}
else
{
kickCurve.transform.localScale = new Vector3(1, 1);
currentKickPathScale = 1;
}*/
//kickCurve.KeyPoints[0].transform.position = holder.transform.position;
//kickPath.positions[0].pos = holder.transform.position;
UpdateLastRealPos();
}
public void HighKick()
{
lastSpriteRot = spriteHolder.transform.eulerAngles.z;
SetState(State.HighKicked);
//highKickCurve.KeyPoints[0].transform.position = holder.transform.position;
//highKickPath.positions[0].pos = holder.transform.position;
UpdateLastRealPos();
}
public void Toe()
{
lastSpriteRot = spriteHolder.transform.eulerAngles.z;
SetState(State.Toe);
//toeCurve.KeyPoints[0].transform.position = holder.transform.position;
//toePath.positions[0].pos = holder.transform.position;
UpdateLastRealPos();
if (lastKickLeft)
{
//toeCurve.KeyPoints[1].transform.localPosition = new Vector3(5.39f, 0);
toePath.positions[1].pos = new Vector3(5.39f, 0);
}
else
{
//toeCurve.KeyPoints[1].transform.localPosition = new Vector3(6.49f, 0);
toePath.positions[1].pos = new Vector3(6.49f, 0);
}
}
private void Update()
{
double beat = Conductor.instance.songPositionInBeatsAsDouble;
switch (state) //handle animations
{
case State.None: //the only time any ball should ever have this state is if it's the unused offscreen ball (which is the only reason this state exists)
{
gameObject.SetActive(false);
break;
}
case State.Dispensing:
{
float normalizedBeatAnim = Conductor.instance.GetPositionFromBeat(startBeat, 2.35f);
//dispenseCurve.KeyPoints[0].transform.position = new Vector3(kicker.transform.GetChild(0).position.x - 6f, kicker.transform.GetChild(0).position.y - 6f);
//dispenseCurve.KeyPoints[1].transform.position = new Vector3(kicker.transform.GetChild(0).position.x - 1f, kicker.transform.GetChild(0).position.y - 6f);
//holder.transform.localPosition = dispenseCurve.GetPoint(normalizedBeatAnim);
holder.transform.localPosition = GetPathPositionFromBeat(dispensePath, Math.Max(beat, startBeat), out double height, startBeat);
spriteHolder.transform.eulerAngles = new Vector3(0, 0, Mathf.Lerp(0f, -1440f, normalizedBeatAnim));
break;
}
case State.Kicked:
{
float normalizedBeatAnim = Conductor.instance.GetPositionFromBeat(startBeat, 1.5f);
if (!lastKickLeft)
{
//kickCurve.KeyPoints[1].transform.position = new Vector3(kicker.transform.GetChild(0).position.x + 0.5f, kicker.transform.GetChild(0).position.y - 6f);
kickPath.positions[1].pos = new Vector3(0, -6f);
spriteHolder.transform.eulerAngles = new Vector3(0, 0, Mathf.Lerp(lastSpriteRot, lastSpriteRot - 360f, normalizedBeatAnim));
}
else
{
//kickCurve.KeyPoints[1].transform.position = new Vector3(kicker.transform.GetChild(0).position.x - 2.5f, kicker.transform.GetChild(0).position.y - 6f);
kickPath.positions[1].pos = new Vector3(-2.5f, -6f);
spriteHolder.transform.eulerAngles = new Vector3(0, 0, Mathf.Lerp(lastSpriteRot, lastSpriteRot + 360f, normalizedBeatAnim));
}
//holder.transform.localPosition = kickCurve.GetPoint(normalizedBeatAnim);
holder.transform.localPosition = GetPathPositionFromBeat(kickPath, Math.Max(beat, startBeat), out double height, startBeat);
break;
}
case State.HighKicked:
{
float normalizedBeatAnim = Conductor.instance.GetPositionFromBeat(startBeat, GetAnimLength(State.HighKicked) + 0.3f);
highKickPath.positions[0].duration = GetAnimLength(State.HighKicked) + 0.3f;
//highKickCurve.KeyPoints[1].transform.position = new Vector3(kicker.transform.GetChild(0).position.x - 3.5f, kicker.transform.GetChild(0).position.y - 6f);
//holder.transform.localPosition = highKickCurve.GetPoint(normalizedBeatAnim);
holder.transform.localPosition = GetPathPositionFromBeat(highKickPath, Math.Max(beat, startBeat), out double height, startBeat);
spriteHolder.transform.eulerAngles = new Vector3(0, 0, Mathf.Lerp(lastSpriteRot, lastSpriteRot + 360f, normalizedBeatAnim));
break;
}
case State.Toe:
{
//float normalizedBeatAnim = Conductor.instance.GetPositionFromBeat(startBeat, GetAnimLength(State.Toe) + 0.35f);
toePath.positions[0].duration = GetAnimLength(State.Toe) + 0.35f;
if (!lastKickLeft)
{
//toeCurve.KeyPoints[1].transform.position = new Vector3(kicker.transform.GetChild(0).position.x + 0.5f, kicker.transform.GetChild(0).position.y - 6f);
toePath.positions[1].pos = new Vector3(-1.5f, -6f);
}
else
{
//toeCurve.KeyPoints[1].transform.position = new Vector3(kicker.transform.GetChild(0).position.x - 1.0f, kicker.transform.GetChild(0).position.y - 6f);
toePath.positions[1].pos = new Vector3(-0.5f, -6f);
}
//holder.transform.localPosition = toeCurve.GetPoint(normalizedBeatAnim);
holder.transform.localPosition = GetPathPositionFromBeat(toePath, Math.Max(beat, startBeat), out double height, startBeat);
break;
}
}
holder.transform.position = new Vector3(holder.transform.position.x, holder.transform.position.y, kicker.transform.GetChild(0).position.z);
}
private void SetState(State newState)
{
state = newState;
startBeat = nextAnimBeat;
nextAnimBeat += GetAnimLength(newState);
}
public float GetAnimLength(State anim)
{
switch(anim)
{
case State.Dispensing:
return 2f;
case State.Kicked:
return 1f;
case State.HighKicked:
return 2f - highKickSwing;
case State.Toe:
return 2f - (1f - highKickSwing);
default:
Debug.LogError("Ball has invalid state. State number: " + (int)anim);
return 0f;
}
}
}
}