HeavenStudioPlus/Assets/Scripts/Games/TossBoys/TossBoys.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

1276 lines
54 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 AgbTossBoysLoader
{
public static Minigame AddGame(EventCaller eventCaller)
{
return new Minigame("tossBoys", "Toss Boys \n<color=#adadad>(Tosu Bōizu)</color>", "9cfff7", false, false, new List<GameAction>()
{
new GameAction("bop", "Bop")
{
function = delegate { var e = eventCaller.currentEntity; TossBoys.instance.Bop(e.beat, e.length, e["auto"], e["bop"]); },
resizable = true,
parameters = new List<Param>()
{
new Param("bop", true, "Bop", "Toggle if the toss boys should bop for the duration of this event."),
new Param("auto", false, "Bop (Auto)", "Toggle if the toss boys should automatically bop until another Bop event is reached.")
}
},
new GameAction("dispense", "Dispense")
{
function = delegate { var e = eventCaller.currentEntity; TossBoys.instance.Dispense(e.beat, e.length, e["who"], e["auto"], e["interval"], e["ignore"], e["callAuto"], true, e["call"]); },
inactiveFunction = delegate { var e = eventCaller.currentEntity; TossBoys.DispenseSound(e.beat, e["who"], e["call"]); },
defaultLength = 2f,
resizable = true,
parameters = new List<Param>()
{
new Param("who", TossBoys.KidChoice.Akachan, "Target", "Set who will receive the ball."),
new Param("call", false, "Name Call", "Toggle if the non-recieving kids should call the reciever's name."),
//auto dispense stuff
new Param("auto", true, "Auto Redispense", "Toggle if a ball should automatically be redispensed if the player lets it pop prematurely.", new()
{
new((x, _) => (bool)x, new string[] { "interval", "ignore", "callAuto" })
}),
new Param("interval", new EntityTypes.Integer(1, 20, 2), "Redispense Interval", "Set how many passes it should take for a ball to be redispensed."),
new Param("ignore", true, "Ignore Special Passes", "Toggle if the redispense interval should ignore special passes."),
new Param("callAuto", false, "Name Call On Redispense", "Toggle if the recieving kid's name should be called out when a ball is redispensed.")
}
},
new GameAction("pass", "Normal Toss")
{
defaultLength = 2f,
resizable = true,
parameters = new List<Param>()
{
new Param("who", TossBoys.KidChoice.Aokun, "Target", "Set who will receive the ball.")
}
},
new GameAction("dual", "Dual Toss")
{
defaultLength = 1f,
resizable = true,
parameters = new List<Param>()
{
new Param("who", TossBoys.KidChoice.Akachan, "Target", "Set who will receive the ball.")
}
},
new GameAction("high", "High Toss")
{
defaultLength = 3f,
resizable = true,
parameters = new List<Param>()
{
new Param("who", TossBoys.KidChoice.Kiiyan, "Target", "Set who will receive the ball.")
}
},
new GameAction("lightning", "Lightning Toss")
{
defaultLength = 2f,
resizable = true,
parameters = new List<Param>()
{
new Param("who", TossBoys.KidChoice.Aokun, "Target", "Set who will receive the ball.")
}
},
new GameAction("blur", "Blur Toss")
{
defaultLength = 2f
},
new GameAction("pop", "Pop Ball")
{
defaultLength = 1f,
},
new GameAction("changeBG", "Change Background Color")
{
function = delegate {var e = eventCaller.currentEntity; TossBoys.instance.BackgroundColor(e.beat, e.length, e["start"], e["end"], e["ease"]); },
defaultLength = 1f,
resizable = true,
parameters = new List<Param>()
{
new Param("start", TossBoys.defaultBGColor, "Start Color", "Set the color at the start of the event."),
new Param("end", TossBoys.defaultBGColor, "End Color", "Set the color at the end of the event."),
new Param("ease", Util.EasingFunction.Ease.Linear, "Ease", "Set the easing of the action.")
}
},
},
new List<string>() {"agb", "normal"},
"agbtoss", "jp",
new List<string>() {}
);
}
}
}
namespace HeavenStudio.Games
{
using Scripts_TossBoys;
public class TossBoys : Minigame
{
private static Color _defaultBGColor;
public static Color defaultBGColor
{
get
{
ColorUtility.TryParseHtmlString("#62FDBB", out _defaultBGColor);
return _defaultBGColor;
}
}
public enum KidChoice
{
Akachan = 0,
Aokun = 1,
Kiiyan = 2
}
public enum WhichTossKid
{
None = -1,
Akachan = 0,
Aokun = 1,
Kiiyan = 2
}
[Header("Components")]
[SerializeField] TossKid akachan;
[SerializeField] TossKid aokun;
[SerializeField] TossKid kiiyan;
[SerializeField] Animator hatchAnim;
[SerializeField] TossBoysBall ballPrefab;
[SerializeField] GameObject specialAka;
[SerializeField] GameObject specialAo;
[SerializeField] GameObject specialKii;
[SerializeField] TossKid currentSpecialKid;
[SerializeField] SpriteRenderer bg;
[Header("Properties")]
[SerializeField] SuperCurveObject.Path[] ballPaths;
WhichTossKid lastReceiver = WhichTossKid.None;
WhichTossKid currentReceiver = WhichTossKid.None;
public TossBoysBall currentBall = null;
Dictionary<double, RiqEntity> passBallDict = new();
string currentPassType;
public static TossBoys instance;
float currentEventLength;
const int IAAka = IAMAXCAT;
const int IAAo = IAMAXCAT + 1;
const int IAKii = IAMAXCAT + 2;
protected static bool IA_PadDir(out double dt)
{
return PlayerInput.GetPadDown(InputController.ActionsPad.Up, out dt)
|| PlayerInput.GetPadDown(InputController.ActionsPad.Down, out dt)
|| PlayerInput.GetPadDown(InputController.ActionsPad.Left, out dt)
|| PlayerInput.GetPadDown(InputController.ActionsPad.Right, out dt);
}
protected static bool IA_PadAlt(out double dt)
{
return PlayerInput.GetPadDown(InputController.ActionsPad.South, out dt);
}
protected static bool IA_TouchNrm(out double dt)
{
return PlayerInput.GetTouchDown(InputController.ActionsTouch.Tap, out dt)
&& (instance.currentReceiver is WhichTossKid.Akachan
|| (instance.lastReceiver is WhichTossKid.Akachan or WhichTossKid.None
&& instance.currentReceiver is WhichTossKid.None)
|| (instance.IsExpectingInputNow(InputAction_Aka)
&& !(instance.IsExpectingInputNow(InputAction_Ao) || instance.IsExpectingInputNow(InputAction_Kii))));
}
protected static bool IA_TouchDir(out double dt)
{
return PlayerInput.GetTouchDown(InputController.ActionsTouch.Tap, out dt)
&& (instance.currentReceiver is WhichTossKid.Kiiyan
|| (instance.lastReceiver is WhichTossKid.Kiiyan
&& instance.currentReceiver is WhichTossKid.None)
|| (instance.IsExpectingInputNow(InputAction_Kii)
&& !(instance.IsExpectingInputNow(InputAction_Ao) || instance.IsExpectingInputNow(InputAction_Aka))));
}
protected static bool IA_TouchAlt(out double dt)
{
return PlayerInput.GetTouchDown(InputController.ActionsTouch.Tap, out dt)
&& (instance.currentReceiver is WhichTossKid.Aokun
|| (instance.lastReceiver is WhichTossKid.Aokun
&& instance.currentReceiver is WhichTossKid.None)
|| (instance.IsExpectingInputNow(InputAction_Ao)
&& !(instance.IsExpectingInputNow(InputAction_Aka) || instance.IsExpectingInputNow(InputAction_Kii))));
}
protected static bool IA_BatonNrm(out double dt)
{
return PlayerInput.GetBatonDown(InputController.ActionsBaton.Face, out dt)
&& (instance.currentReceiver is WhichTossKid.Akachan
|| (instance.lastReceiver is WhichTossKid.Akachan or WhichTossKid.None
&& instance.currentReceiver is WhichTossKid.None)
|| (instance.IsExpectingInputNow(InputAction_Aka)
&& !(instance.IsExpectingInputNow(InputAction_Ao) || instance.IsExpectingInputNow(InputAction_Kii))));
}
protected static bool IA_BatonDir(out double dt)
{
return PlayerInput.GetBatonDown(InputController.ActionsBaton.Face, out dt)
&& (instance.currentReceiver is WhichTossKid.Kiiyan
|| (instance.lastReceiver is WhichTossKid.Kiiyan
&& instance.currentReceiver is WhichTossKid.None)
|| (instance.IsExpectingInputNow(InputAction_Ao)
&& !(instance.IsExpectingInputNow(InputAction_Aka) || instance.IsExpectingInputNow(InputAction_Kii))));
}
protected static bool IA_BatonAlt(out double dt)
{
return PlayerInput.GetBatonDown(InputController.ActionsBaton.Face, out dt)
&& (instance.currentReceiver is WhichTossKid.Aokun
|| (instance.lastReceiver is WhichTossKid.Aokun
&& instance.currentReceiver is WhichTossKid.None));
}
public static PlayerInput.InputAction InputAction_Aka =
new("BasicPress", new int[] { IAAka, IAAka, IAAka },
IA_PadBasicPress, IA_TouchNrm, IA_BatonNrm);
public static PlayerInput.InputAction InputAction_Ao =
new("BasicPress", new int[] { IAAo, IAAo, IAAo },
IA_PadAlt, IA_TouchAlt, IA_BatonAlt);
public static PlayerInput.InputAction InputAction_Kii =
new("BasicPress", new int[] { IAKii, IAKii, IAKii },
IA_PadDir, IA_TouchDir, IA_BatonDir);
private void Awake()
{
instance = this;
colorStart = defaultBGColor;
colorEnd = defaultBGColor;
SetupBopRegion("tossBoys", "bop", "auto");
SetPassBallEvents();
}
new void OnDrawGizmos()
{
base.OnDrawGizmos();
foreach (SuperCurveObject.Path path in ballPaths)
{
if (path.preview)
{
ballPrefab.DrawEditorGizmo(path);
}
}
}
public SuperCurveObject.Path GetPath(string name)
{
foreach (SuperCurveObject.Path path in ballPaths)
{
if (path.name == name)
{
return path;
}
}
return default(SuperCurveObject.Path);
}
public override void OnBeatPulse(double beat)
{
if (BeatIsInBopRegion(beat))
{
SingleBop();
}
}
private void Update()
{
var cond = Conductor.instance;
BackgroundColorUpdate();
if (cond.isPlaying && !cond.isPaused)
{
if (PlayerInput.GetIsAction(InputAction_Aka) && !IsExpectingInputNow(InputAction_Aka))
{
akachan.HitBall(false);
}
if (PlayerInput.GetIsAction(InputAction_Ao) && !IsExpectingInputNow(InputAction_Ao))
{
aokun.HitBall(false);
}
if (PlayerInput.GetIsAction(InputAction_Kii) && !IsExpectingInputNow(InputAction_Kii))
{
kiiyan.HitBall(false);
}
}
}
private double colorStartBeat = -1;
private float colorLength = 0f;
private Color colorStart = Color.white; //obviously put to the default color of the game
private Color colorEnd = Color.white;
private Util.EasingFunction.Ease colorEase; //putting Util in case this game is using jukebox
//call this in update
private void BackgroundColorUpdate()
{
float normalizedBeat = Mathf.Clamp01(Conductor.instance.GetPositionFromBeat(colorStartBeat, colorLength));
var func = Util.EasingFunction.GetEasingFunction(colorEase);
float newR = func(colorStart.r, colorEnd.r, normalizedBeat);
float newG = func(colorStart.g, colorEnd.g, normalizedBeat);
float newB = func(colorStart.b, colorEnd.b, normalizedBeat);
bg.color = new Color(newR, newG, newB);
}
public void BackgroundColor(double beat, float length, Color colorStartSet, Color colorEndSet, int ease)
{
colorStartBeat = beat;
colorLength = length;
colorStart = colorStartSet;
colorEnd = colorEndSet;
colorEase = (Util.EasingFunction.Ease)ease;
}
//call this in OnPlay(double beat) and OnGameSwitch(double beat)
private void PersistColor(double beat)
{
var allEventsBeforeBeat = EventCaller.GetAllInGameManagerList("tossBoys", new string[] { "changeBG" }).FindAll(x => x.beat < beat);
if (allEventsBeforeBeat.Count > 0)
{
allEventsBeforeBeat.Sort((x, y) => x.beat.CompareTo(y.beat)); //just in case
var lastEvent = allEventsBeforeBeat[^1];
BackgroundColor(lastEvent.beat, lastEvent.length, lastEvent["start"], lastEvent["end"], lastEvent["ease"]);
}
}
public override void OnPlay(double beat)
{
PersistColor(beat);
}
public override void OnGameSwitch(double beat)
{
PersistColor(beat);
HandleDispenses(beat);
}
private void HandleDispenses(double beat)
{
var allRelevantDispenses = EventCaller.GetAllInGameManagerList("tossBoys", new string[] { "dispense" }).FindAll(x => x.beat < beat && x.beat + x.length >= beat);
if (allRelevantDispenses.Count == 0) return;
var e = allRelevantDispenses[^1];
Dispense(e.beat, e.length, e["who"], e["auto"], e["interval"], e["ignore"], e["callAuto"], false, e["call"]);
}
#region Bop
void SingleBop()
{
akachan.Bop();
aokun.Bop();
kiiyan.Bop();
}
public void Bop(double beat, float length, bool auto, bool goBop)
{
if (goBop)
{
List<BeatAction.Action> bops = new List<BeatAction.Action>();
for (int i = 0; i < length; i++)
{
bops.Add(new BeatAction.Action(beat + i, delegate { SingleBop(); }));
}
BeatAction.New(instance, bops);
}
}
#endregion
public static void DispenseSound(double beat, int who, bool call)
{
SoundByte.PlayOneShotGame("tossBoys/ballStart" + GetColorBasedOnTossKid((WhichTossKid)who, true), beat, forcePlay: true);
if (!call) return;
double callBeat = beat;
switch (who)
{
case (int)WhichTossKid.Akachan:
MultiSound.Play(new MultiSound.Sound[]
{
new MultiSound.Sound("tossBoys/blueRedHigh1", callBeat),
new MultiSound.Sound("tossBoys/yellowRedHigh1", callBeat),
new MultiSound.Sound("tossBoys/blueRedHigh2", callBeat + 0.25f),
new MultiSound.Sound("tossBoys/yellowRedHigh2", callBeat + 0.25f),
new MultiSound.Sound("tossBoys/blueRedHigh3", callBeat + 0.5f),
new MultiSound.Sound("tossBoys/yellowRedHigh3", callBeat + 0.5f),
}, forcePlay: true);
break;
case (int)WhichTossKid.Aokun:
MultiSound.Play(new MultiSound.Sound[]
{
new MultiSound.Sound("tossBoys/redBlueHigh1", callBeat),
new MultiSound.Sound("tossBoys/yellowBlueHigh1", callBeat),
new MultiSound.Sound("tossBoys/redBlueHigh2", callBeat + 0.5f),
new MultiSound.Sound("tossBoys/yellowBlueHigh2", callBeat + 0.5f),
}, forcePlay: true);
break;
case (int)WhichTossKid.Kiiyan:
MultiSound.Play(new MultiSound.Sound[]
{
new MultiSound.Sound("tossBoys/redYellowHigh1", callBeat),
new MultiSound.Sound("tossBoys/blueYellowHigh1", callBeat),
new MultiSound.Sound("tossBoys/redYellowHigh2", callBeat + 0.5f),
new MultiSound.Sound("tossBoys/blueYellowHigh2", callBeat + 0.5f),
}, forcePlay: true);
break;
default:
break;
}
}
public void Dispense(double beat, float length, int who, bool auto, int autoInterval, bool ignoreSpecial, bool callAuto, bool playSound, bool call)
{
if (playSound) DispenseSound(beat, who, call);
DispenseExec(beat, length, who, false, "");
if (auto && passBallDict.TryGetValue(beat + length, out var e))
{
if (e.datamodel == "tossBoys/blur")
{
DispenseRecursion(beat + length, -1, autoInterval, ignoreSpecial, callAuto, (int)WhichTossKid.None, who, false, e.length, true, true, e.datamodel);
}
else DispenseRecursion(beat + length, -1, autoInterval, ignoreSpecial, callAuto, e["who"], who, false, e.length, IsSpecialEvent(e.datamodel), false, e.datamodel);
}
}
public void DispenseRecursion(double beat, int index, int interval, bool ignore, bool call, int curReceiver, int previousReceiver, bool isBlur, float currentLength, bool isSpecial, bool shouldForce, string eventDatamodel)
{
if (index % interval == 0 && !isBlur && !(ignore && isSpecial))
{
double dispenseBeat = beat - 2;
BeatAction.New(this, new()
{
new(dispenseBeat, delegate
{
if (currentBall != null) return;
DispenseSound(dispenseBeat, curReceiver, call);
DispenseExec(dispenseBeat, 2, curReceiver, shouldForce, eventDatamodel);
})
});
}
if (!isBlur && !(ignore && isSpecial)) index++;
var tempLastReceiver = previousReceiver;
var lastLength = isBlur ? 1 : currentLength;
previousReceiver = curReceiver;
var nextIsSpecial = isSpecial;
var blurSet = isBlur;
var nextForce = false;
if (passBallDict.TryGetValue(beat + lastLength, out var e))
{
if (e.datamodel == "tossBoys/pop") return;
curReceiver = e["who"];
blurSet = e.datamodel == "tossBoys/blur";
currentLength = e.length;
nextIsSpecial = IsSpecialEvent(e.datamodel);
eventDatamodel = e.datamodel;
}
else
{
curReceiver = tempLastReceiver;
nextForce = true;
}
// let's not do a stack overflow, alright?
BeatAction.New(this, new()
{
new(beat + lastLength - 2, delegate { DispenseRecursion(beat + lastLength, index, interval, ignore, call, curReceiver, previousReceiver, blurSet, currentLength, nextIsSpecial, nextForce, eventDatamodel); })
});
}
public void DispenseExec(double beat, float length, int who, bool forcePass, string eventDatamodel)
{
if (currentBall != null) return;
SetReceiver(who);
GetCurrentReceiver().ShowArrow(beat, length - 1);
hatchAnim.Play("HatchOpen", 0, 0);
currentBall = Instantiate(ballPrefab, transform);
currentBall.gameObject.SetActive(true);
switch (who)
{
case (int)WhichTossKid.Akachan:
currentBall.SetState(TossBoysBall.State.RedDispense, beat, length);
break;
case (int)WhichTossKid.Aokun:
currentBall.SetState(TossBoysBall.State.BlueDispense, beat, length);
break;
case (int)WhichTossKid.Kiiyan:
currentBall.SetState(TossBoysBall.State.YellowDispense, beat, length);
break;
default:
break;
}
if (passBallDict.ContainsKey(beat + length))
{
ScheduleInput(beat, length, GetInputTypeBasedOnCurrentReceiver(), JustHitBall, Miss, Empty);
if (IsSpecialEvent(passBallDict[beat + length].datamodel))
{
BeatAction.New(instance, new List<BeatAction.Action>()
{
new BeatAction.Action(beat + length - 1, delegate { DoSpecialBasedOnReceiver(beat + length - 1); })
});
}
else if (passBallDict[beat + length].datamodel == "tossBoys/pop")
{
currentBall.willBePopped = true;
if (PlayerInput.CurrentControlStyle != InputController.ControlStyles.Touch)
BeatAction.New(instance, new List<BeatAction.Action>()
{
new BeatAction.Action(beat + length - 1, delegate { GetCurrentReceiver().PopBallPrepare(); })
});
}
}
else if (forcePass)
{
ScheduleInput(beat, length, GetInputTypeBasedOnCurrentReceiver(), JustHitBall, Miss, Empty);
if (IsSpecialEvent(eventDatamodel))
{
BeatAction.New(instance, new List<BeatAction.Action>()
{
new BeatAction.Action(beat + length - 1, delegate { DoSpecialBasedOnReceiver(beat + length - 1); })
});
}
else if (eventDatamodel == "tossBoys/pop")
{
currentBall.willBePopped = true;
if (PlayerInput.CurrentControlStyle != InputController.ControlStyles.Touch)
BeatAction.New(instance, new List<BeatAction.Action>()
{
new BeatAction.Action(beat + length - 1, delegate { GetCurrentReceiver().PopBallPrepare(); })
});
}
}
else
{
BeatAction.New(instance, new List<BeatAction.Action>()
{
new BeatAction.Action(beat + length, delegate { Miss(null); })
});
}
}
void SetPassBallEvents()
{
passBallDict.Clear();
var passBallEvents = EventCaller.GetAllInGameManagerList("tossBoys", new string[] { "pass", "dual", "pop", "high", "lightning", "blur" });
for (int i = 0; i < passBallEvents.Count; i++)
{
if (passBallDict.ContainsKey(passBallEvents[i].beat)) continue;
passBallDict.Add(passBallEvents[i].beat, passBallEvents[i]);
}
}
private void DeterminePassValues(double beat)
{
var tempLastReceiver = lastReceiver;
lastReceiver = currentReceiver;
if (passBallDict.TryGetValue(beat, out var receiver))
{
if (receiver.datamodel != "tossBoys/blur") currentReceiver = (WhichTossKid)receiver["who"];
currentPassType = receiver.datamodel;
currentEventLength = receiver.length;
}
else
{
currentReceiver = tempLastReceiver;
}
}
void DeterminePass(double beat, bool barely)
{
DeterminePassValues(beat);
switch (currentPassType)
{
case "tossBoys/pass":
PassBall(beat, currentEventLength);
break;
case "tossBoys/dual":
DualToss(beat, currentEventLength);
break;
case "tossBoys/high":
HighToss(beat, currentEventLength);
break;
case "tossBoys/lightning":
LightningToss(beat, currentEventLength);
break;
default:
break;
}
currentBall.anim.DoScaledAnimationAsync(barely ? "WiggleBall" : "Hit", 0.5f);
if (passBallDict.ContainsKey(beat + currentEventLength) && passBallDict[beat + currentEventLength].datamodel == "tossBoys/pop")
{
currentBall.willBePopped = true;
if (PlayerInput.CurrentControlStyle != InputController.ControlStyles.Touch)
BeatAction.New(instance, new List<BeatAction.Action>()
{
new BeatAction.Action(beat + currentEventLength - 1, delegate { GetCurrentReceiver().PopBallPrepare(); })
});
}
}
void PassBall(double beat, float length)
{
string last = GetColorBasedOnTossKid(lastReceiver, false);
string current = GetColorBasedOnTossKid(currentReceiver, true);
float secondBeat = 1f;
float secondOffset = 0;
float thirdOffset = 0;
if (currentBall != null)
{
switch (last + current)
{
case "redBlue":
currentBall.SetState(TossBoysBall.State.RedBlue, beat, length);
break;
case "blueRed":
secondBeat = 0.5f;
currentBall.SetState(TossBoysBall.State.BlueRed, beat, length);
break;
case "blueYellow":
currentBall.SetState(TossBoysBall.State.BlueYellow, beat, length);
break;
case "yellowRed":
secondBeat = 0.5f;
currentBall.SetState(TossBoysBall.State.YellowRed, beat, length);
break;
case "redYellow":
secondBeat = 0.5f;
thirdOffset = 0.060f;
currentBall.SetState(TossBoysBall.State.RedYellow, beat, length);
break;
case "yellowBlue":
currentBall.SetState(TossBoysBall.State.YellowBlue, beat, length);
break;
default:
break;
}
}
List<MultiSound.Sound> soundsToPlay = new List<MultiSound.Sound>()
{
new MultiSound.Sound("tossBoys/" + last + current + 1, beat),
new MultiSound.Sound("tossBoys/" + last + current + 2, beat + secondBeat, 1, 1, false, secondOffset),
};
if (passBallDict.ContainsKey(beat + length) && (passBallDict[beat + length].datamodel is "tossBoys/dual" or "tossBoys/lightning" or "tossBoys/blur"))
{
BeatAction.New(instance, new List<BeatAction.Action>()
{
new BeatAction.Action(beat + length - 1, delegate { DoSpecialBasedOnReceiver(beat + length - 1); })
});
}
if (secondBeat == 0.5f) soundsToPlay.Add(new MultiSound.Sound("tossBoys/" + last + current + 3, beat + 1, 1, 1, false, thirdOffset));
MultiSound.Play(soundsToPlay.ToArray());
ScheduleInput(beat, length, GetInputTypeBasedOnCurrentReceiver(), JustHitBall, Miss, Empty);
}
void DualToss(double beat, float length)
{
string last = GetColorBasedOnTossKid(lastReceiver, false);
string current = GetColorBasedOnTossKid(currentReceiver, true);
float secondBeat = 0.5f;
float secondOffset = 0;
float thirdOffset = 0;
if (currentBall != null)
{
switch (last + current)
{
case "redBlue":
currentBall.SetState(TossBoysBall.State.RedBlueDual, beat, length);
break;
case "blueYellow":
currentBall.SetState(TossBoysBall.State.BlueYellowDual, beat, length);
break;
case "yellowBlue":
currentBall.SetState(TossBoysBall.State.YellowBlueDual, beat, length);
break;
case "blueRed":
secondBeat = 0.25f;
thirdOffset = 0.020f;
currentBall.SetState(TossBoysBall.State.BlueRedDual, beat, length);
break;
case "yellowRed":
secondBeat = 0.25f;
currentBall.SetState(TossBoysBall.State.YellowRedDual, beat, length);
break;
case "redYellow":
secondOffset = 0.060f;
currentBall.SetState(TossBoysBall.State.RedYellowDual, beat, length);
break;
default:
break;
}
}
List<MultiSound.Sound> soundsToPlay = new List<MultiSound.Sound>()
{
new MultiSound.Sound("tossBoys/" + last + current + "Low" + 1, beat),
new MultiSound.Sound("tossBoys/" + last + current + "Low" + 2, beat + secondBeat, 1, 1, false, secondOffset),
};
if (passBallDict.ContainsKey(beat + length) && (passBallDict[beat + length].datamodel is "tossBoys/lightning" or "tossBoys/blur"))
{
BeatAction.New(instance, new List<BeatAction.Action>()
{
new BeatAction.Action(beat + length - 1, delegate { DoSpecialBasedOnReceiver(beat + length - 1); })
});
}
if (secondBeat == 0.25f) soundsToPlay.Add(new MultiSound.Sound("tossBoys/" + last + current + "Low" + 3, beat + 0.5f, 1, 1, false, thirdOffset));
MultiSound.Play(soundsToPlay.ToArray());
bool stopSpecial = passBallDict.ContainsKey(beat + length) && passBallDict[beat + length].datamodel is "tossBoys/pass" or "tossBoys/high" or "tossBoys/pop";
ScheduleInput(beat, length, GetInputTypeBasedOnCurrentReceiver(), stopSpecial ? JustHitBallUnSpecial : JustHitBall, Miss, Empty);
}
void HighToss(double beat, float length)
{
string last = GetColorBasedOnTossKid(lastReceiver, false);
string current = GetColorBasedOnTossKid(currentReceiver, true);
float secondBeat = 0.5f;
float secondOffset = 0;
float thirdOffset = 0;
if (currentBall != null)
{
switch (last + current)
{
case "redBlue":
currentBall.SetState(TossBoysBall.State.RedBlueHigh, beat, length);
break;
case "redYellow":
currentBall.SetState(TossBoysBall.State.RedYellowHigh, beat, length);
break;
case "blueYellow":
currentBall.SetState(TossBoysBall.State.BlueYellowHigh, beat, length);
break;
case "yellowBlue":
currentBall.SetState(TossBoysBall.State.YellowBlueHigh, beat, length);
break;
case "yellowRed":
secondBeat = 0.25f;
currentBall.SetState(TossBoysBall.State.YellowRedHigh, beat, length);
break;
case "blueRed":
secondBeat = 0.25f;
currentBall.SetState(TossBoysBall.State.BlueRedHigh, beat, length);
break;
default:
break;
}
}
List<MultiSound.Sound> soundsToPlay = new List<MultiSound.Sound>()
{
new MultiSound.Sound("tossBoys/" + last + current + "High" + 1, beat),
new MultiSound.Sound("tossBoys/" + last + current + "High" + 2, beat + secondBeat, 1, 1, false, secondOffset),
};
if (passBallDict.ContainsKey(beat + length) && (passBallDict[beat + length].datamodel is "tossBoys/dual" or "tossBoys/lightning" or "tossBoys/blur"))
{
BeatAction.New(instance, new List<BeatAction.Action>()
{
new BeatAction.Action(beat + length - 1, delegate { DoSpecialBasedOnReceiver(beat + length - 1); })
});
}
if (secondBeat == 0.25f) soundsToPlay.Add(new MultiSound.Sound("tossBoys/" + last + current + "High" + 3, beat + 0.5f, 1, 1, false, thirdOffset));
MultiSound.Play(soundsToPlay.ToArray());
ScheduleInput(beat, length, GetInputTypeBasedOnCurrentReceiver(), JustHitBall, Miss, Empty);
}
void LightningToss(double beat, float length)
{
string last = GetColorBasedOnTossKid(lastReceiver, false);
string current = GetColorBasedOnTossKid(currentReceiver, true);
float secondBeat = 0.5f;
float secondOffset = 0;
float thirdOffset = 0;
switch (last + current)
{
case "blueRed":
secondBeat = 0.25f;
thirdOffset = 0.020f;
break;
case "yellowRed":
secondBeat = 0.25f;
break;
case "redYellow":
secondOffset = 0.060f;
break;
default:
secondBeat = 0.5f;
break;
}
if (currentBall != null)
{
switch (last)
{
case "blue":
currentBall.SetState(TossBoysBall.State.BlueKeep, beat, length / 2);
break;
case "red":
currentBall.SetState(TossBoysBall.State.RedKeep, beat, length / 2);
break;
case "yellow":
currentBall.SetState(TossBoysBall.State.YellowKeep, beat, length / 2);
break;
}
}
List<MultiSound.Sound> soundsToPlay = new List<MultiSound.Sound>()
{
new MultiSound.Sound("tossBoys/" + last + current + "Low" + 1, beat),
new MultiSound.Sound("tossBoys/" + last + current + "Low" + 2, beat + secondBeat, 1, 1, false, secondOffset),
};
if (secondBeat == 0.25f) soundsToPlay.Add(new MultiSound.Sound("tossBoys/" + last + current + "Low" + 3, beat + 0.5f, 1, 1, false, thirdOffset));
if (passBallDict.ContainsKey(beat + length) && (passBallDict[beat + length].datamodel is "tossBoys/dual" or "tossBoys/blur"))
{
BeatAction.New(instance, new List<BeatAction.Action>()
{
new BeatAction.Action(beat + length - 1, delegate { DoSpecialBasedOnReceiver(beat + length - 1); })
});
}
MultiSound.Play(soundsToPlay.ToArray());
bool stopSpecial = passBallDict.ContainsKey(beat + length) && passBallDict[beat + length].datamodel is "tossBoys/pass" or "tossBoys/high" or "tossBoys/pop";
ScheduleInput(beat, length / 2, GetInputBasedOnTossKid(lastReceiver), stopSpecial ? JustKeepUnSpecial : JustKeep, Miss, Empty);
ScheduleInput(beat, length, GetInputTypeBasedOnCurrentReceiver(), JustHitBall, Miss, Empty);
}
void BlurToss(double beat)
{
string current = GetColorBasedOnTossKid(currentReceiver, false);
if (currentBall != null)
{
switch (current)
{
case "blue":
currentBall.SetState(TossBoysBall.State.BlueBlur, beat);
break;
case "red":
currentBall.SetState(TossBoysBall.State.RedBlur, beat);
break;
case "yellow":
currentBall.SetState(TossBoysBall.State.YellowBlur, beat);
break;
}
}
ScheduleInput(beat, 2f, GetInputTypeBasedOnCurrentReceiver(), JustKeepContinue, Miss, Empty);
}
#region Inputs
void JustHitBall(PlayerActionEvent caller, float state)
{
if (currentBall == null) return;
if (passBallDict.ContainsKey(caller.startBeat + caller.timer))
{
if (passBallDict[caller.startBeat + caller.timer].datamodel == "tossBoys/pop")
{
GetCurrentReceiver().PopBall();
Destroy(currentBall.gameObject);
currentBall = null;
switch (currentReceiver)
{
case WhichTossKid.Akachan:
SoundByte.PlayOneShotGame("tossBoys/redPop");
break;
case WhichTossKid.Aokun:
SoundByte.PlayOneShotGame("tossBoys/bluePop");
break;
case WhichTossKid.Kiiyan:
SoundByte.PlayOneShotGame("tossBoys/yellowPop");
break;
default:
break;
}
return;
}
if (passBallDict[caller.startBeat + caller.timer].datamodel == "tossBoys/blur")
{
JustKeepCurrent(caller, state);
BlurToss(caller.startBeat + caller.timer);
return;
}
if ((WhichTossKid)passBallDict[caller.startBeat + caller.timer]["who"] == currentReceiver)
{
Miss(null);
return;
}
}
if (state >= 1f || state <= -1f)
{
GetCurrentReceiver().Barely();
DeterminePass(caller.timer + caller.startBeat, true);
return;
}
GetCurrentReceiver().HitBall();
DeterminePass(caller.timer + caller.startBeat, false);
}
void JustHitBallUnSpecial(PlayerActionEvent caller, float state)
{
if (currentBall == null) return;
specialAo.SetActive(false);
specialAka.SetActive(false);
specialKii.SetActive(false);
currentSpecialKid.crouch = false;
if (passBallDict.ContainsKey(caller.startBeat + caller.timer))
{
if (passBallDict[caller.startBeat + caller.timer].datamodel == "tossBoys/pop")
{
GetCurrentReceiver().PopBall();
Destroy(currentBall.gameObject);
currentBall = null;
switch (currentReceiver)
{
case WhichTossKid.Akachan:
SoundByte.PlayOneShotGame("tossBoys/redPop");
break;
case WhichTossKid.Aokun:
SoundByte.PlayOneShotGame("tossBoys/bluePop");
break;
case WhichTossKid.Kiiyan:
SoundByte.PlayOneShotGame("tossBoys/yellowPop");
break;
default:
break;
}
return;
}
if (passBallDict[caller.startBeat + caller.timer].datamodel == "tossBoys/blur")
{
JustKeepCurrentUnSpecial(caller, state);
BlurToss(caller.startBeat + caller.timer);
return;
}
if ((WhichTossKid)passBallDict[caller.startBeat + caller.timer]["who"] == currentReceiver)
{
Miss(null);
return;
}
}
if (state >= 1f || state <= -1f)
{
GetCurrentReceiver().Barely();
DeterminePass(caller.timer + caller.startBeat, true);
return;
}
GetCurrentReceiver().HitBall();
DeterminePass(caller.timer + caller.startBeat, false);
}
void JustKeepContinue(PlayerActionEvent caller, float state)
{
if (currentBall == null) return;
if (passBallDict.ContainsKey(caller.timer + caller.startBeat))
{
if (passBallDict[caller.timer + caller.startBeat].datamodel is "tossBoys/pass" or "tossBoys/high" or "tossBoys/pop")
{
JustHitBallUnSpecial(caller, state);
}
else
{
JustHitBall(caller, state);
}
}
else
{
JustKeepCurrent(caller, state);
ScheduleInput(caller.timer + caller.startBeat, 1f, GetInputTypeBasedOnCurrentReceiver(), JustKeepContinue, Miss, Empty);
}
}
void JustKeepCurrent(PlayerActionEvent caller, float state)
{
if (currentBall == null) return;
SoundByte.PlayOneShotGame("tossBoys/" + GetColorBasedOnTossKid(currentReceiver, false) + "Keep");
string current = GetColorBasedOnTossKid(currentReceiver, false);
double beat = caller.timer + caller.startBeat;
if (currentBall != null)
{
switch (current)
{
case "blue":
currentBall.SetState(TossBoysBall.State.BlueKeep, beat);
break;
case "red":
currentBall.SetState(TossBoysBall.State.RedKeep, beat);
break;
case "yellow":
currentBall.SetState(TossBoysBall.State.YellowKeep, beat);
break;
}
}
if (state >= 1f || state <= -1f)
{
currentBall.anim.DoScaledAnimationAsync("WiggleBall", 0.5f);
GetCurrentReceiver().Barely();
return;
}
GetCurrentReceiver().HitBall();
currentBall.anim.DoScaledAnimationAsync("Hit", 0.5f);
}
void JustKeepCurrentUnSpecial(PlayerActionEvent caller, float state)
{
if (currentBall == null) return;
specialAo.SetActive(false);
specialAka.SetActive(false);
specialKii.SetActive(false);
currentSpecialKid.crouch = false;
SoundByte.PlayOneShotGame("tossBoys/" + GetColorBasedOnTossKid(currentReceiver, false) + "Keep");
if (state >= 1f || state <= -1f)
{
currentBall.anim.DoScaledAnimationAsync("WiggleBall", 0.5f);
GetCurrentReceiver().Barely();
return;
}
GetCurrentReceiver().HitBall();
currentBall.anim.DoScaledAnimationAsync("Hit", 0.5f);
}
void JustKeep(PlayerActionEvent caller, float state)
{
if (currentBall == null) return;
SoundByte.PlayOneShotGame("tossBoys/" + GetColorBasedOnTossKid(lastReceiver, false) + "Keep");
string last = GetColorBasedOnTossKid(lastReceiver, false);
string current = GetColorBasedOnTossKid(currentReceiver, true);
double beat = caller.timer + caller.startBeat;
if (currentBall != null)
{
switch (last + current)
{
case "redBlue":
currentBall.SetState(TossBoysBall.State.RedBlueDual, beat, currentEventLength / 2);
break;
case "blueYellow":
currentBall.SetState(TossBoysBall.State.BlueYellowDual, beat, currentEventLength / 2);
break;
case "yellowBlue":
currentBall.SetState(TossBoysBall.State.YellowBlueDual, beat, currentEventLength / 2);
break;
case "blueRed":
currentBall.SetState(TossBoysBall.State.BlueRedDual, beat, currentEventLength / 2);
break;
case "yellowRed":
currentBall.SetState(TossBoysBall.State.YellowRedDual, beat, currentEventLength / 2);
break;
case "redYellow":
currentBall.SetState(TossBoysBall.State.RedYellowDual, beat, currentEventLength / 2);
break;
default:
break;
}
}
if (state >= 1f || state <= -1f)
{
currentBall.anim.DoScaledAnimationAsync("WiggleBall", 0.5f);
GetReceiver(lastReceiver).Barely();
return;
}
GetReceiver(lastReceiver).HitBall();
currentBall.anim.DoScaledAnimationAsync("Hit", 0.5f);
}
void JustKeepUnSpecial(PlayerActionEvent caller, float state)
{
if (currentBall == null) return;
specialAo.SetActive(false);
specialAka.SetActive(false);
specialKii.SetActive(false);
currentSpecialKid.crouch = false;
SoundByte.PlayOneShotGame("tossBoys/" + GetColorBasedOnTossKid(lastReceiver, false) + "Keep");
string last = GetColorBasedOnTossKid(lastReceiver, false);
string current = GetColorBasedOnTossKid(currentReceiver, true);
double beat = caller.timer + caller.startBeat;
if (currentBall != null)
{
switch (last + current)
{
case "redBlue":
currentBall.SetState(TossBoysBall.State.RedBlueDual, beat);
break;
case "blueYellow":
currentBall.SetState(TossBoysBall.State.BlueYellowDual, beat);
break;
case "yellowBlue":
currentBall.SetState(TossBoysBall.State.YellowBlueDual, beat);
break;
case "blueRed":
currentBall.SetState(TossBoysBall.State.BlueRedDual, beat);
break;
case "yellowRed":
currentBall.SetState(TossBoysBall.State.YellowRedDual, beat);
break;
case "redYellow":
currentBall.SetState(TossBoysBall.State.RedYellowDual, beat);
break;
default:
break;
}
}
if (state >= 1f || state <= -1f)
{
currentBall.anim.DoScaledAnimationAsync("WiggleBall", 0.5f);
GetReceiver(lastReceiver).Barely();
return;
}
GetReceiver(lastReceiver).HitBall();
currentBall.anim.DoScaledAnimationAsync("Hit", 0.5f);
}
void Miss(PlayerActionEvent caller)
{
if (currentBall == null) return;
GetCurrentReceiver().Miss();
aokun.crouch = false;
akachan.crouch = false;
kiiyan.crouch = false;
specialAo.SetActive(false);
specialAka.SetActive(false);
specialKii.SetActive(false);
Destroy(currentBall.gameObject);
currentBall = null;
SoundByte.PlayOneShotGame("tossBoys/misshit");
if (caller != null) DeterminePassValues(caller.startBeat + caller.timer);
}
void Empty(PlayerActionEvent caller) { }
#endregion
#region HelperFunctions
void DoSpecialBasedOnReceiver(double beat)
{
specialAo.SetActive(false);
specialAka.SetActive(false);
specialKii.SetActive(false);
if (currentSpecialKid != null) currentSpecialKid.crouch = false;
currentSpecialKid = GetCurrentReceiver();
GetCurrentReceiver().Crouch();
GetSpecialBasedOnReceiver().SetActive(true);
switch (currentReceiver)
{
case WhichTossKid.Akachan:
MultiSound.Play(new MultiSound.Sound[]
{
new MultiSound.Sound("tossBoys/redSpecial1", beat),
new MultiSound.Sound("tossBoys/redSpecial2", beat + 0.25f),
new MultiSound.Sound("tossBoys/redSpecialCharge", beat + 0.25f, 1, 1, false, 0.085f),
});
break;
case WhichTossKid.Aokun:
MultiSound.Play(new MultiSound.Sound[]
{
new MultiSound.Sound("tossBoys/blueSpecial1", beat),
new MultiSound.Sound("tossBoys/blueSpecial2", beat + 0.25f),
});
break;
case WhichTossKid.Kiiyan:
SoundByte.PlayOneShotGame("tossBoys/yellowSpecial", beat);
break;
default:
break;
}
}
public TossKid GetCurrentReceiver()
{
return GetReceiver(currentReceiver);
}
public TossKid GetReceiver(WhichTossKid receiver)
{
switch (receiver)
{
case WhichTossKid.Akachan:
return akachan;
case WhichTossKid.Aokun:
return aokun;
case WhichTossKid.Kiiyan:
return kiiyan;
default:
return null;
}
}
public static string GetColorBasedOnTossKid(WhichTossKid tossKid, bool capital)
{
switch (tossKid)
{
case WhichTossKid.Akachan:
return capital ? "Red" : "red";
case WhichTossKid.Aokun:
return capital ? "Blue" : "blue";
case WhichTossKid.Kiiyan:
return capital ? "Yellow" : "yellow";
default:
return "";
}
}
public void SetReceiver(int who)
{
currentReceiver = (WhichTossKid)who;
}
PlayerInput.InputAction GetInputTypeBasedOnCurrentReceiver()
{
return GetInputBasedOnTossKid(currentReceiver);
}
PlayerInput.InputAction GetInputBasedOnTossKid(WhichTossKid tossKid)
{
switch (tossKid)
{
case WhichTossKid.Aokun:
return InputAction_Ao;
case WhichTossKid.Kiiyan:
return InputAction_Kii;
default:
return InputAction_Aka;
}
}
GameObject GetSpecialBasedOnReceiver()
{
switch (currentReceiver)
{
case WhichTossKid.Akachan:
return specialAka;
case WhichTossKid.Aokun:
return specialAo;
case WhichTossKid.Kiiyan:
return specialKii;
default:
return null;
}
}
private bool IsSpecialEvent(string e)
{
bool b = false;
switch (e)
{
case "tossBoys/dual":
case "tossBoys/lightning":
case "tossBoys/blur":
b = true; break;
default:
return b;
}
return b;
}
#endregion
}
}