2022-02-08 14:26:55 +00:00
|
|
|
using System.Collections;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using UnityEngine;
|
2022-02-09 10:29:09 +00:00
|
|
|
using System;
|
2024-02-16 06:17:16 +00:00
|
|
|
|
2022-02-09 10:29:09 +00:00
|
|
|
using DG.Tweening;
|
2022-03-14 14:21:05 +00:00
|
|
|
using HeavenStudio.Util;
|
2023-10-29 19:44:47 +00:00
|
|
|
using HeavenStudio.InputSystem;
|
2022-02-08 14:26:55 +00:00
|
|
|
|
2022-04-12 16:14:46 +00:00
|
|
|
namespace HeavenStudio.Games.Loaders
|
|
|
|
{
|
|
|
|
using static Minigames;
|
|
|
|
public static class AgbHairLoader
|
|
|
|
{
|
|
|
|
public static Minigame AddGame(EventCaller eventCaller) {
|
2023-04-02 02:28:23 +00:00
|
|
|
return new Minigame("rhythmTweezers", "Rhythm Tweezers", "a14fa1", false, false, new List<GameAction>()
|
2022-04-12 16:14:46 +00:00
|
|
|
{
|
2022-08-20 23:03:51 +00:00
|
|
|
new GameAction("start interval", "Start Interval")
|
2022-04-12 16:14:46 +00:00
|
|
|
{
|
2023-06-28 04:51:53 +00:00
|
|
|
preFunction = delegate { RhythmTweezers.PreInterval(eventCaller.currentEntity.beat, eventCaller.currentEntity.length, eventCaller.currentEntity["auto"]); },
|
2022-08-20 23:03:51 +00:00
|
|
|
defaultLength = 4f,
|
2023-01-19 02:31:08 +00:00
|
|
|
resizable = true,
|
2023-06-28 04:51:53 +00:00
|
|
|
parameters = new List<Param>()
|
|
|
|
{
|
2024-01-15 02:04:10 +00:00
|
|
|
new Param("auto", true, "Auto Pass Turn", "Toggle if the turn should be passed automatically at the end of the start interval.")
|
2023-06-28 04:51:53 +00:00
|
|
|
}
|
2022-08-20 23:03:51 +00:00
|
|
|
},
|
|
|
|
new GameAction("short hair", "Short Hair")
|
2022-04-12 16:14:46 +00:00
|
|
|
{
|
2022-08-20 23:03:51 +00:00
|
|
|
defaultLength = 0.5f
|
|
|
|
},
|
|
|
|
new GameAction("long hair", "Curly Hair")
|
|
|
|
{
|
|
|
|
defaultLength = 0.5f
|
|
|
|
},
|
2023-05-29 20:09:34 +00:00
|
|
|
new GameAction("passTurn", "Pass Turn")
|
|
|
|
{
|
2023-06-13 14:03:08 +00:00
|
|
|
preFunction = delegate { var e = eventCaller.currentEntity; RhythmTweezers.PrePassTurn(e.beat); },
|
2023-05-29 20:09:34 +00:00
|
|
|
},
|
2022-08-20 23:03:51 +00:00
|
|
|
new GameAction("next vegetable", "Swap Vegetable")
|
|
|
|
{
|
2023-05-29 20:09:34 +00:00
|
|
|
function = delegate
|
|
|
|
{
|
|
|
|
var e = eventCaller.currentEntity;
|
|
|
|
if (!e["instant"]) RhythmTweezers.instance.NextVegetable(e.beat, e["type"], e["colorA"], e["colorB"]);
|
|
|
|
else RhythmTweezers.instance.ChangeVegetableImmediate(e["type"], e["colorA"], e["colorB"]);
|
|
|
|
},
|
2022-08-20 23:03:51 +00:00
|
|
|
defaultLength = 0.5f,
|
|
|
|
parameters = new List<Param>()
|
|
|
|
{
|
2024-01-15 02:04:10 +00:00
|
|
|
new Param("type", RhythmTweezers.VegetableType.Onion, "Type", "Set the vegetable to switch to."),
|
|
|
|
new Param("colorA", RhythmTweezers.defaultOnionColor, "Onion Color", "Set the color of the onion."),
|
|
|
|
new Param("colorB", RhythmTweezers.defaultPotatoColor, "Potato Color", "Set the color of the potato."),
|
|
|
|
new Param("instant", false, "Instant", "Toggle if the vegetable should skip the moving animation and instantly swap.")
|
2023-01-19 02:31:08 +00:00
|
|
|
},
|
|
|
|
priority = 3
|
2022-08-20 23:03:51 +00:00
|
|
|
},
|
2023-05-29 20:09:34 +00:00
|
|
|
new GameAction("noPeek", "No Peeking Sign")
|
2022-08-20 23:03:51 +00:00
|
|
|
{
|
2023-06-03 14:51:30 +00:00
|
|
|
preFunction = delegate { var e = eventCaller.currentEntity; RhythmTweezers.PreNoPeeking(e.beat, e.length, e["type"]); },
|
2023-05-29 20:09:34 +00:00
|
|
|
defaultLength = 4f,
|
2023-06-03 14:51:30 +00:00
|
|
|
resizable = true,
|
|
|
|
parameters = new List<Param>()
|
|
|
|
{
|
2024-01-15 02:04:10 +00:00
|
|
|
new Param("type", RhythmTweezers.NoPeekSignType.Full, "Side", "Set the side for the sign to appear on.")
|
2023-06-03 14:51:30 +00:00
|
|
|
}
|
2023-05-29 20:09:34 +00:00
|
|
|
},
|
2024-01-15 02:04:10 +00:00
|
|
|
new GameAction("fade background color", "Background Appearance")
|
2023-05-29 20:09:34 +00:00
|
|
|
{
|
|
|
|
function = delegate
|
|
|
|
{
|
2023-08-12 03:30:03 +00:00
|
|
|
var e = eventCaller.currentEntity;
|
|
|
|
RhythmTweezers.instance.BackgroundColor(e.beat, e.length, e["colorA"], e["colorB"], e["ease"]);
|
2023-05-29 20:09:34 +00:00
|
|
|
},
|
|
|
|
resizable = true,
|
2022-08-20 23:03:51 +00:00
|
|
|
parameters = new List<Param>()
|
|
|
|
{
|
2024-01-15 02:04:10 +00:00
|
|
|
new Param("colorA", Color.white, "Start Color", "Set the color at the start of the event."),
|
|
|
|
new Param("colorB", RhythmTweezers.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.")
|
2023-05-29 20:09:34 +00:00
|
|
|
}
|
2022-08-20 23:03:51 +00:00
|
|
|
},
|
2023-05-29 20:09:34 +00:00
|
|
|
new GameAction("altSmile", "Use Alt Smile")
|
2022-08-20 23:03:51 +00:00
|
|
|
{
|
2023-05-29 20:09:34 +00:00
|
|
|
function = delegate
|
|
|
|
{
|
|
|
|
RhythmTweezers.instance.VegetableAnimator.SetBool("UseAltSmile", !RhythmTweezers.instance.VegetableAnimator.GetBool("UseAltSmile"));
|
|
|
|
},
|
|
|
|
defaultLength = 0.5f
|
2022-08-20 23:03:51 +00:00
|
|
|
},
|
2023-05-29 20:09:34 +00:00
|
|
|
//backwards compatibility
|
|
|
|
new GameAction("change vegetable", "Change Vegetable (Instant)")
|
2022-08-20 23:03:51 +00:00
|
|
|
{
|
2023-05-29 20:09:34 +00:00
|
|
|
function = delegate { var e = eventCaller.currentEntity; RhythmTweezers.instance.ChangeVegetableImmediate(e["type"], e["colorA"], e["colorB"]); },
|
2023-01-19 02:31:08 +00:00
|
|
|
defaultLength = 0.5f,
|
2023-05-29 20:09:34 +00:00
|
|
|
parameters = new List<Param>()
|
|
|
|
{
|
|
|
|
new Param("type", RhythmTweezers.VegetableType.Onion, "Type", "The vegetable to switch to"),
|
|
|
|
new Param("colorA", RhythmTweezers.defaultOnionColor, "Onion Color", "The color of the onion"),
|
|
|
|
new Param("colorB", RhythmTweezers.defaultPotatoColor, "Potato Color", "The color of the potato")
|
|
|
|
},
|
|
|
|
hidden = true,
|
2022-08-20 23:03:51 +00:00
|
|
|
},
|
2023-05-28 17:34:44 +00:00
|
|
|
},
|
|
|
|
new List<string>() {"agb", "repeat"},
|
|
|
|
"agbhair", "en",
|
|
|
|
new List<string>() {}
|
|
|
|
);
|
2022-04-12 16:14:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-14 14:21:05 +00:00
|
|
|
namespace HeavenStudio.Games
|
2022-02-08 14:26:55 +00:00
|
|
|
{
|
2023-06-28 04:51:53 +00:00
|
|
|
using Jukebox;
|
2022-03-12 04:10:13 +00:00
|
|
|
using Scripts_RhythmTweezers;
|
|
|
|
|
2022-02-08 14:26:55 +00:00
|
|
|
public class RhythmTweezers : Minigame
|
|
|
|
{
|
2022-02-20 13:31:55 +00:00
|
|
|
public enum VegetableType
|
|
|
|
{
|
|
|
|
Onion,
|
|
|
|
Potato
|
|
|
|
}
|
|
|
|
|
2023-06-03 14:51:30 +00:00
|
|
|
public enum NoPeekSignType
|
|
|
|
{
|
|
|
|
Full,
|
|
|
|
HalfRight,
|
|
|
|
HalfLeft
|
|
|
|
}
|
|
|
|
|
2023-05-29 20:09:34 +00:00
|
|
|
private struct QueuedPeek
|
|
|
|
{
|
2023-06-10 19:13:29 +00:00
|
|
|
public double beat;
|
2023-05-29 20:09:34 +00:00
|
|
|
public float length;
|
2023-06-03 14:51:30 +00:00
|
|
|
public int type;
|
2023-05-29 20:09:34 +00:00
|
|
|
}
|
|
|
|
|
2022-02-13 14:02:55 +00:00
|
|
|
[Header("References")]
|
2022-02-09 10:29:09 +00:00
|
|
|
public Transform VegetableHolder;
|
2022-02-13 14:02:55 +00:00
|
|
|
public SpriteRenderer Vegetable;
|
|
|
|
public SpriteRenderer VegetableDupe;
|
2022-02-09 06:52:50 +00:00
|
|
|
public Animator VegetableAnimator;
|
2022-02-17 12:11:06 +00:00
|
|
|
public SpriteRenderer bg;
|
2022-02-09 06:52:50 +00:00
|
|
|
public Tweezers Tweezers;
|
2023-06-28 04:51:53 +00:00
|
|
|
private Tweezers currentTweezers;
|
2022-02-09 10:29:09 +00:00
|
|
|
public GameObject hairBase;
|
2022-02-10 08:13:54 +00:00
|
|
|
public GameObject longHairBase;
|
2022-02-10 15:29:53 +00:00
|
|
|
public GameObject pluckedHairBase;
|
2023-06-03 14:51:30 +00:00
|
|
|
[SerializeField] NoPeekingSign noPeekingRef;
|
2022-02-09 03:58:25 +00:00
|
|
|
|
2022-02-10 10:14:15 +00:00
|
|
|
public GameObject HairsHolder;
|
2022-02-10 15:29:53 +00:00
|
|
|
public GameObject DroppedHairsHolder;
|
2022-02-09 03:58:25 +00:00
|
|
|
|
2022-02-13 14:02:55 +00:00
|
|
|
[Header("Variables")]
|
2023-05-29 20:09:34 +00:00
|
|
|
private static List<QueuedPeek> queuedPeeks = new List<QueuedPeek>();
|
2022-02-09 10:29:09 +00:00
|
|
|
|
2022-02-13 14:02:55 +00:00
|
|
|
[Header("Sprites")]
|
2022-02-10 15:29:53 +00:00
|
|
|
public Sprite pluckedHairSprite;
|
|
|
|
public Sprite missedHairSprite;
|
2022-02-13 14:02:55 +00:00
|
|
|
public Sprite onionSprite;
|
|
|
|
public Sprite potatoSprite;
|
2022-02-10 15:29:53 +00:00
|
|
|
|
2022-02-09 10:29:09 +00:00
|
|
|
bool transitioning = false;
|
2022-02-09 03:58:25 +00:00
|
|
|
|
2022-02-13 14:02:55 +00:00
|
|
|
private static Color _defaultOnionColor;
|
|
|
|
public static Color defaultOnionColor
|
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
|
|
|
ColorUtility.TryParseHtmlString("#C89600", out _defaultOnionColor);
|
|
|
|
return _defaultOnionColor;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private static Color _defaultPotatoColor;
|
|
|
|
public static Color defaultPotatoColor
|
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
|
|
|
ColorUtility.TryParseHtmlString("#FFDC00", out _defaultPotatoColor);
|
|
|
|
return _defaultPotatoColor;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-17 12:11:06 +00:00
|
|
|
private static Color _defaultBgColor;
|
|
|
|
public static Color defaultBgColor
|
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
2022-06-24 04:51:22 +00:00
|
|
|
ColorUtility.TryParseHtmlString("#A14FA1", out _defaultBgColor);
|
2022-02-17 12:11:06 +00:00
|
|
|
return _defaultBgColor;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-09 03:58:25 +00:00
|
|
|
public static RhythmTweezers instance { get; set; }
|
2023-05-29 20:09:34 +00:00
|
|
|
private static CallAndResponseHandler crHandlerInstance;
|
|
|
|
|
|
|
|
private List<Hair> spawnedHairs = new List<Hair>();
|
|
|
|
private List<LongHair> spawnedLongs = new List<LongHair>();
|
|
|
|
|
2023-06-10 19:13:29 +00:00
|
|
|
private static List<double> passedTurns = new();
|
2023-06-28 04:51:53 +00:00
|
|
|
private struct QueuedInterval
|
|
|
|
{
|
|
|
|
public double beat;
|
|
|
|
public float interval;
|
|
|
|
public bool autoPassTurn;
|
|
|
|
}
|
|
|
|
private static List<QueuedInterval> queuedIntervals = new List<QueuedInterval>();
|
2023-05-29 20:09:34 +00:00
|
|
|
|
2023-10-29 19:44:47 +00:00
|
|
|
protected static bool IA_PadAnyDown(out double dt)
|
|
|
|
{
|
|
|
|
return PlayerInput.GetPadDown(InputController.ActionsPad.East, out dt)
|
|
|
|
|| 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_PadAnyUp(out double dt)
|
|
|
|
{
|
|
|
|
bool face = PlayerInput.GetPadUp(InputController.ActionsPad.East, out dt)
|
|
|
|
&& !(PlayerInput.GetPad(InputController.ActionsPad.Up)
|
|
|
|
|| PlayerInput.GetPad(InputController.ActionsPad.Down)
|
|
|
|
|| PlayerInput.GetPad(InputController.ActionsPad.Left)
|
|
|
|
|| PlayerInput.GetPad(InputController.ActionsPad.Right));
|
|
|
|
bool pad = (PlayerInput.GetPadUp(InputController.ActionsPad.Up)
|
|
|
|
|| PlayerInput.GetPadUp(InputController.ActionsPad.Down)
|
|
|
|
|| PlayerInput.GetPadUp(InputController.ActionsPad.Left)
|
|
|
|
|| PlayerInput.GetPadUp(InputController.ActionsPad.Right))
|
|
|
|
&& !PlayerInput.GetPad(InputController.ActionsPad.East);
|
|
|
|
return face || pad;
|
|
|
|
}
|
|
|
|
public static PlayerInput.InputAction InputAction_Press =
|
|
|
|
new("AgbHairPress", new int[] { IAPressCat, IAPressCat, IAPressCat },
|
|
|
|
IA_PadAnyDown, IA_TouchBasicPress, IA_BatonBasicPress);
|
|
|
|
public static PlayerInput.InputAction InputAction_Release =
|
|
|
|
new("AgbHairRelease", new int[] { IAReleaseCat, IAReleaseCat, IAReleaseCat },
|
|
|
|
IA_PadAnyUp, IA_TouchBasicRelease, IA_BatonBasicRelease);
|
|
|
|
|
2022-02-09 03:58:25 +00:00
|
|
|
private void Awake()
|
2022-02-08 14:26:55 +00:00
|
|
|
{
|
2022-02-09 03:58:25 +00:00
|
|
|
instance = this;
|
2023-08-12 03:30:03 +00:00
|
|
|
colorStart = defaultBgColor;
|
|
|
|
colorEnd = defaultBgColor;
|
2023-06-28 04:51:53 +00:00
|
|
|
if (crHandlerInstance != null && crHandlerInstance.queuedEvents.Count > 0)
|
2023-05-29 20:09:34 +00:00
|
|
|
{
|
|
|
|
foreach (var crEvent in crHandlerInstance.queuedEvents)
|
|
|
|
{
|
|
|
|
if (crEvent.tag == "Hair")
|
|
|
|
{
|
|
|
|
Hair hair = Instantiate(hairBase, HairsHolder.transform).GetComponent<Hair>();
|
|
|
|
spawnedHairs.Add(hair);
|
|
|
|
hair.gameObject.SetActive(true);
|
|
|
|
hair.GetComponent<Animator>().Play("SmallAppear", 0, 1);
|
2024-02-16 06:17:16 +00:00
|
|
|
float rot = -58f + 116 * MathUtils.Normalize((float)crEvent.relativeBeat, 0, crHandlerInstance.intervalLength - 1);
|
2023-05-29 20:09:34 +00:00
|
|
|
hair.transform.eulerAngles = new Vector3(0, 0, rot);
|
|
|
|
hair.createBeat = crEvent.beat;
|
|
|
|
}
|
|
|
|
else if (crEvent.tag == "Long")
|
|
|
|
{
|
|
|
|
LongHair hair = Instantiate(longHairBase, HairsHolder.transform).GetComponent<LongHair>();
|
|
|
|
spawnedLongs.Add(hair);
|
|
|
|
hair.gameObject.SetActive(true);
|
|
|
|
hair.GetComponent<Animator>().Play("LongAppear", 0, 1);
|
2024-02-16 06:17:16 +00:00
|
|
|
float rot = -58f + 116 * MathUtils.Normalize((float)crEvent.relativeBeat, 0, crHandlerInstance.intervalLength - 1);
|
2023-05-29 20:09:34 +00:00
|
|
|
hair.transform.eulerAngles = new Vector3(0, 0, rot);
|
|
|
|
hair.createBeat = crEvent.beat;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-28 04:51:53 +00:00
|
|
|
public override void OnPlay(double beat)
|
|
|
|
{
|
|
|
|
crHandlerInstance = null;
|
2024-01-15 02:04:10 +00:00
|
|
|
foreach (var evt in scheduledInputs)
|
|
|
|
{
|
|
|
|
evt.Disable();
|
|
|
|
}
|
|
|
|
queuedIntervals.Clear();
|
2024-01-06 20:08:22 +00:00
|
|
|
PersistBlocks(beat);
|
2023-06-28 04:51:53 +00:00
|
|
|
}
|
|
|
|
|
2023-05-29 20:09:34 +00:00
|
|
|
private void OnDestroy()
|
|
|
|
{
|
2023-06-28 04:51:53 +00:00
|
|
|
if (!Conductor.instance.isPlaying)
|
2023-05-29 20:09:34 +00:00
|
|
|
{
|
|
|
|
crHandlerInstance = null;
|
|
|
|
}
|
2023-06-03 23:30:17 +00:00
|
|
|
foreach (var evt in scheduledInputs)
|
|
|
|
{
|
|
|
|
evt.Disable();
|
|
|
|
}
|
2023-05-29 20:09:34 +00:00
|
|
|
}
|
|
|
|
|
2023-06-28 04:51:53 +00:00
|
|
|
private void SpawnHairInactive(double beat)
|
2023-05-29 20:09:34 +00:00
|
|
|
{
|
|
|
|
if (crHandlerInstance.queuedEvents.Count > 0 && crHandlerInstance.queuedEvents.Find(x => x.beat == beat || (beat >= x.beat && beat <= x.beat + x.length)) != null) return;
|
|
|
|
crHandlerInstance.AddEvent(beat, 0, "Hair");
|
2023-06-28 04:51:53 +00:00
|
|
|
Hair hair = Instantiate(hairBase, HairsHolder.transform).GetComponent<Hair>();
|
|
|
|
spawnedHairs.Add(hair);
|
|
|
|
hair.gameObject.SetActive(true);
|
|
|
|
hair.GetComponent<Animator>().Play("SmallAppear", 0, 1);
|
|
|
|
float rot = -58f + 116 * crHandlerInstance.GetIntervalProgressFromBeat(beat, 1);
|
|
|
|
hair.transform.eulerAngles = new Vector3(0, 0, rot);
|
|
|
|
hair.createBeat = beat;
|
2023-05-29 20:09:34 +00:00
|
|
|
}
|
|
|
|
|
2023-06-28 04:51:53 +00:00
|
|
|
private void SpawnLongHairInactive(double beat)
|
2023-05-29 20:09:34 +00:00
|
|
|
{
|
|
|
|
if (crHandlerInstance.queuedEvents.Count > 0 && crHandlerInstance.queuedEvents.Find(x => x.beat == beat || (beat >= x.beat && beat <= x.beat + x.length)) != null) return;
|
|
|
|
crHandlerInstance.AddEvent(beat, 0.5f, "Long");
|
2023-06-28 04:51:53 +00:00
|
|
|
LongHair hair = Instantiate(longHairBase, HairsHolder.transform).GetComponent<LongHair>();
|
|
|
|
spawnedLongs.Add(hair);
|
|
|
|
hair.gameObject.SetActive(true);
|
|
|
|
hair.GetComponent<Animator>().Play("LongAppear", 0, 1);
|
|
|
|
float rot = -58f + 116 * crHandlerInstance.GetIntervalProgressFromBeat(beat, 1);
|
|
|
|
hair.transform.eulerAngles = new Vector3(0, 0, rot);
|
|
|
|
hair.createBeat = beat;
|
2022-02-09 03:58:25 +00:00
|
|
|
}
|
2022-02-08 14:26:55 +00:00
|
|
|
|
2023-06-10 19:13:29 +00:00
|
|
|
public void SpawnHair(double beat)
|
2022-02-09 03:58:25 +00:00
|
|
|
{
|
2023-05-29 20:09:34 +00:00
|
|
|
if (crHandlerInstance.queuedEvents.Count > 0 && crHandlerInstance.queuedEvents.Find(x => x.beat == beat || (beat >= x.beat && beat <= x.beat + x.length)) != null) return;
|
2022-02-09 10:29:09 +00:00
|
|
|
// End transition early if the next hair is a lil early.
|
|
|
|
StopTransitionIfActive();
|
|
|
|
|
2023-05-29 20:09:34 +00:00
|
|
|
crHandlerInstance.AddEvent(beat, 0, "Hair");
|
2022-02-09 10:29:09 +00:00
|
|
|
|
2023-06-10 19:13:29 +00:00
|
|
|
SoundByte.PlayOneShotGame("rhythmTweezers/shortAppear", beat);
|
2023-06-28 04:51:53 +00:00
|
|
|
Hair hair = Instantiate(hairBase, transform).GetComponent<Hair>();
|
2023-05-29 20:09:34 +00:00
|
|
|
spawnedHairs.Add(hair);
|
2023-06-28 04:51:53 +00:00
|
|
|
|
2023-09-11 22:28:04 +00:00
|
|
|
BeatAction.New(instance, new List<BeatAction.Action>()
|
2023-06-28 04:51:53 +00:00
|
|
|
{
|
|
|
|
new BeatAction.Action(beat, delegate
|
|
|
|
{
|
|
|
|
hair.gameObject.SetActive(true);
|
|
|
|
hair.GetComponent<Animator>().Play("SmallAppear", 0, 0);
|
|
|
|
hair.transform.SetParent(HairsHolder.transform, false);
|
|
|
|
})
|
|
|
|
});
|
2022-02-09 10:29:09 +00:00
|
|
|
|
2023-05-29 20:09:34 +00:00
|
|
|
float rot = -58f + 116 * crHandlerInstance.GetIntervalProgressFromBeat(beat, 1);
|
2022-02-10 08:13:54 +00:00
|
|
|
hair.transform.eulerAngles = new Vector3(0, 0, rot);
|
|
|
|
hair.createBeat = beat;
|
|
|
|
}
|
|
|
|
|
2023-06-10 19:13:29 +00:00
|
|
|
public void SpawnLongHair(double beat)
|
2022-02-10 08:13:54 +00:00
|
|
|
{
|
2023-05-29 20:09:34 +00:00
|
|
|
if (crHandlerInstance.queuedEvents.Count > 0 && crHandlerInstance.queuedEvents.Find(x => x.beat == beat || (beat >= x.beat && beat <= x.beat + x.length)) != null) return;
|
2022-02-10 08:13:54 +00:00
|
|
|
StopTransitionIfActive();
|
|
|
|
|
2023-05-29 20:09:34 +00:00
|
|
|
crHandlerInstance.AddEvent(beat, 0.5f, "Long");
|
2022-02-10 08:13:54 +00:00
|
|
|
|
2023-06-10 19:13:29 +00:00
|
|
|
SoundByte.PlayOneShotGame("rhythmTweezers/longAppear", beat);
|
2023-06-28 04:51:53 +00:00
|
|
|
LongHair hair = Instantiate(longHairBase, transform).GetComponent<LongHair>();
|
2023-05-29 20:09:34 +00:00
|
|
|
spawnedLongs.Add(hair);
|
2023-09-11 22:28:04 +00:00
|
|
|
BeatAction.New(instance, new List<BeatAction.Action>()
|
2023-06-28 04:51:53 +00:00
|
|
|
{
|
|
|
|
new BeatAction.Action(beat, delegate
|
|
|
|
{
|
|
|
|
hair.gameObject.SetActive(true);
|
|
|
|
hair.GetComponent<Animator>().Play("LongAppear", 0, 0);
|
|
|
|
hair.transform.SetParent(HairsHolder.transform, false);
|
|
|
|
})
|
|
|
|
});
|
2022-02-10 08:13:54 +00:00
|
|
|
|
2023-05-29 20:09:34 +00:00
|
|
|
float rot = -58f + 116 * crHandlerInstance.GetIntervalProgressFromBeat(beat, 1);
|
2022-02-09 10:29:09 +00:00
|
|
|
hair.transform.eulerAngles = new Vector3(0, 0, rot);
|
|
|
|
hair.createBeat = beat;
|
2022-02-08 14:26:55 +00:00
|
|
|
}
|
|
|
|
|
2023-06-28 04:51:53 +00:00
|
|
|
private void SetIntervalStart(double beat, double gameSwitchBeat, float interval = 4f, bool autoPassTurn = true)
|
2022-02-08 14:26:55 +00:00
|
|
|
{
|
2023-05-29 20:09:34 +00:00
|
|
|
StopTransitionIfActive();
|
2023-06-28 04:51:53 +00:00
|
|
|
CallAndResponseHandler newHandler = new();
|
|
|
|
crHandlerInstance = newHandler;
|
2023-05-29 20:09:34 +00:00
|
|
|
crHandlerInstance.StartInterval(beat, interval);
|
2023-06-28 04:51:53 +00:00
|
|
|
List<RiqEntity> relevantHairEvents = GetAllHairsInBetweenBeat(beat, beat + interval);
|
|
|
|
foreach (var hairEvent in relevantHairEvents)
|
|
|
|
{
|
|
|
|
if (hairEvent.beat >= gameSwitchBeat)
|
|
|
|
{
|
|
|
|
if (hairEvent.datamodel == "rhythmTweezers/short hair")
|
|
|
|
{
|
|
|
|
SpawnHair(hairEvent.beat);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SpawnLongHair(hairEvent.beat);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (hairEvent.datamodel == "rhythmTweezers/short hair")
|
|
|
|
{
|
|
|
|
SpawnHairInactive(hairEvent.beat);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SpawnLongHairInactive(hairEvent.beat);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (autoPassTurn)
|
|
|
|
{
|
|
|
|
PassTurn(beat + interval, interval, newHandler);
|
|
|
|
}
|
2023-05-29 20:09:34 +00:00
|
|
|
}
|
|
|
|
|
2023-06-28 04:51:53 +00:00
|
|
|
public static void PreInterval(double beat, float interval = 4f, bool autoPassTurn = true)
|
2023-05-29 20:09:34 +00:00
|
|
|
{
|
2023-06-28 04:51:53 +00:00
|
|
|
if (GameManager.instance.currentGame == "rhythmTweezers")
|
2023-05-29 20:09:34 +00:00
|
|
|
{
|
2023-06-28 04:51:53 +00:00
|
|
|
instance.SetIntervalStart(beat, beat, interval, autoPassTurn);
|
2023-05-29 20:09:34 +00:00
|
|
|
}
|
2023-06-28 04:51:53 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
queuedIntervals.Add(new QueuedInterval()
|
|
|
|
{
|
|
|
|
beat = beat,
|
|
|
|
interval = interval,
|
|
|
|
autoPassTurn = autoPassTurn
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private static List<RiqEntity> GetAllHairsInBetweenBeat(double beat, double endBeat)
|
|
|
|
{
|
|
|
|
List<RiqEntity> hairEvents = EventCaller.GetAllInGameManagerList("rhythmTweezers", new string[] { "short hair", "long hair"});
|
|
|
|
List<RiqEntity> tempEvents = new();
|
|
|
|
|
|
|
|
foreach (var entity in hairEvents)
|
|
|
|
{
|
|
|
|
if (entity.beat >= beat && entity.beat < endBeat)
|
|
|
|
{
|
|
|
|
tempEvents.Add(entity);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return tempEvents;
|
|
|
|
}
|
|
|
|
|
|
|
|
private void PassTurnStandalone(double beat)
|
|
|
|
{
|
|
|
|
if (crHandlerInstance != null) PassTurn(beat, crHandlerInstance.intervalLength, crHandlerInstance);
|
2023-05-29 20:09:34 +00:00
|
|
|
}
|
|
|
|
|
2023-06-28 04:51:53 +00:00
|
|
|
private void PassTurn(double beat, double length, CallAndResponseHandler crHandler)
|
2023-05-29 20:09:34 +00:00
|
|
|
{
|
2023-06-28 04:51:53 +00:00
|
|
|
Tweezers spawnedTweezers = Instantiate(Tweezers, transform);
|
|
|
|
spawnedTweezers.gameObject.SetActive(true);
|
|
|
|
spawnedTweezers.Init(beat, beat + length);
|
2023-09-11 22:28:04 +00:00
|
|
|
BeatAction.New(instance, new List<BeatAction.Action>()
|
2023-05-29 20:09:34 +00:00
|
|
|
{
|
2023-06-28 04:51:53 +00:00
|
|
|
new BeatAction.Action(beat - 0.25, delegate
|
2023-06-12 09:58:31 +00:00
|
|
|
{
|
2023-06-28 04:51:53 +00:00
|
|
|
if (crHandler.queuedEvents.Count > 0)
|
2023-06-13 14:03:08 +00:00
|
|
|
{
|
2023-06-28 04:51:53 +00:00
|
|
|
currentTweezers = spawnedTweezers;
|
|
|
|
spawnedTweezers.hairsLeft = crHandler.queuedEvents.Count;
|
|
|
|
foreach (var crEvent in crHandler.queuedEvents)
|
2023-06-13 14:03:08 +00:00
|
|
|
{
|
|
|
|
if (crEvent.tag == "Hair")
|
|
|
|
{
|
|
|
|
Hair hairToInput = spawnedHairs.Find(x => x.createBeat == crEvent.beat);
|
2023-06-28 04:51:53 +00:00
|
|
|
hairToInput.StartInput(beat, crEvent.relativeBeat, spawnedTweezers);
|
2023-06-13 14:03:08 +00:00
|
|
|
}
|
|
|
|
else if (crEvent.tag == "Long")
|
|
|
|
{
|
|
|
|
LongHair hairToInput = spawnedLongs.Find(x => x.createBeat == crEvent.beat);
|
2023-06-28 04:51:53 +00:00
|
|
|
hairToInput.StartInput(beat, crEvent.relativeBeat, spawnedTweezers);
|
2023-06-13 14:03:08 +00:00
|
|
|
}
|
|
|
|
}
|
2023-06-28 04:51:53 +00:00
|
|
|
crHandler.queuedEvents.Clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
}),
|
|
|
|
});
|
2023-05-29 20:09:34 +00:00
|
|
|
}
|
|
|
|
|
2023-06-13 14:03:08 +00:00
|
|
|
public static void PrePassTurn(double beat)
|
2023-05-29 20:09:34 +00:00
|
|
|
{
|
|
|
|
if (GameManager.instance.currentGame == "rhythmTweezers")
|
2022-02-10 10:14:15 +00:00
|
|
|
{
|
2023-06-28 04:51:53 +00:00
|
|
|
instance.PassTurnStandalone(beat);
|
2022-02-10 10:14:15 +00:00
|
|
|
}
|
2023-05-29 20:09:34 +00:00
|
|
|
else
|
|
|
|
{
|
2023-06-13 14:03:08 +00:00
|
|
|
passedTurns.Add(beat);
|
2023-05-29 20:09:34 +00:00
|
|
|
}
|
|
|
|
}
|
2022-02-09 10:29:09 +00:00
|
|
|
|
2023-08-12 03:30:03 +00:00
|
|
|
Tween transitionTween;
|
|
|
|
|
2022-02-09 10:29:09 +00:00
|
|
|
const float vegDupeOffset = 16.7f;
|
2023-06-10 19:13:29 +00:00
|
|
|
public void NextVegetable(double beat, int type, Color onionColor, Color potatoColor)
|
2022-02-09 10:29:09 +00:00
|
|
|
{
|
|
|
|
transitioning = true;
|
2022-02-09 03:58:25 +00:00
|
|
|
|
2023-06-10 19:13:29 +00:00
|
|
|
SoundByte.PlayOneShotGame("rhythmTweezers/register", beat);
|
2022-02-08 14:26:55 +00:00
|
|
|
|
2022-02-13 14:02:55 +00:00
|
|
|
Sprite nextVeggieSprite = type == 0 ? onionSprite : potatoSprite;
|
|
|
|
Color nextColor = type == 0 ? onionColor : potatoColor;
|
|
|
|
|
|
|
|
VegetableDupe.sprite = nextVeggieSprite;
|
|
|
|
VegetableDupe.color = nextColor;
|
|
|
|
|
2022-02-09 10:29:09 +00:00
|
|
|
// Move both vegetables to the left by vegDupeOffset, then reset their positions.
|
|
|
|
// On position reset, reset state of core vegetable.
|
2022-02-24 14:02:21 +00:00
|
|
|
transitionTween = VegetableHolder.DOLocalMoveX(-vegDupeOffset, Conductor.instance.secPerBeat * 0.5f / Conductor.instance.musicSource.pitch)
|
2022-02-09 10:29:09 +00:00
|
|
|
.OnComplete(() => {
|
|
|
|
|
|
|
|
var holderPos = VegetableHolder.localPosition;
|
|
|
|
VegetableHolder.localPosition = new Vector3(0f, holderPos.y, holderPos.z);
|
|
|
|
|
2022-02-13 14:02:55 +00:00
|
|
|
Vegetable.sprite = nextVeggieSprite;
|
|
|
|
Vegetable.color = nextColor;
|
|
|
|
|
2022-02-09 10:29:09 +00:00
|
|
|
ResetVegetable();
|
|
|
|
transitioning = false;
|
|
|
|
|
|
|
|
}).SetEase(Ease.InOutSine);
|
2022-02-09 03:58:25 +00:00
|
|
|
}
|
|
|
|
|
2022-02-13 14:02:55 +00:00
|
|
|
public void ChangeVegetableImmediate(int type, Color onionColor, Color potatoColor)
|
|
|
|
{
|
|
|
|
StopTransitionIfActive();
|
|
|
|
|
|
|
|
Sprite newSprite = type == 0 ? onionSprite : potatoSprite;
|
|
|
|
Color newColor = type == 0 ? onionColor : potatoColor;
|
|
|
|
|
|
|
|
Vegetable.sprite = newSprite;
|
|
|
|
Vegetable.color = newColor;
|
|
|
|
VegetableDupe.sprite = newSprite;
|
|
|
|
VegetableDupe.color = newColor;
|
|
|
|
}
|
|
|
|
|
2023-08-12 03:30:03 +00:00
|
|
|
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()
|
2022-02-17 12:11:06 +00:00
|
|
|
{
|
2023-08-12 03:30:03 +00:00
|
|
|
float normalizedBeat = Mathf.Clamp01(Conductor.instance.GetPositionFromBeat(colorStartBeat, colorLength));
|
2022-02-17 12:11:06 +00:00
|
|
|
|
2023-08-12 03:30:03 +00:00
|
|
|
var func = Util.EasingFunction.GetEasingFunction(colorEase);
|
2022-02-17 12:11:06 +00:00
|
|
|
|
2023-08-12 03:30:03 +00:00
|
|
|
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);
|
2022-02-17 12:11:06 +00:00
|
|
|
}
|
|
|
|
|
2023-08-12 03:30:03 +00:00
|
|
|
public void BackgroundColor(double beat, float length, Color colorStartSet, Color colorEndSet, int ease)
|
2022-02-17 12:11:06 +00:00
|
|
|
{
|
2023-08-12 03:30:03 +00:00
|
|
|
colorStartBeat = beat;
|
|
|
|
colorLength = length;
|
|
|
|
colorStart = colorStartSet;
|
|
|
|
colorEnd = colorEndSet;
|
|
|
|
colorEase = (Util.EasingFunction.Ease)ease;
|
|
|
|
}
|
|
|
|
|
|
|
|
//call this in OnPlay(double beat) and OnGameSwitch(double beat)
|
2024-01-06 20:08:22 +00:00
|
|
|
private void PersistBlocks(double beat)
|
2023-08-12 03:30:03 +00:00
|
|
|
{
|
2024-01-06 20:08:22 +00:00
|
|
|
var allEventsBeforeBeat = GameManager.instance.Beatmap.Entities.FindAll(x => x.datamodel.Split('/')[0] == "rhythmTweezers" && x.beat < beat);
|
|
|
|
var allColorEventsBeforeBeat = allEventsBeforeBeat.FindAll(x => x.datamodel == "rhythmTweezers/fade background color");
|
|
|
|
if (allColorEventsBeforeBeat.Count > 0)
|
2023-08-12 03:30:03 +00:00
|
|
|
{
|
2024-01-06 20:08:22 +00:00
|
|
|
allColorEventsBeforeBeat.Sort((x, y) => x.beat.CompareTo(y.beat)); //just in case
|
|
|
|
var lastEvent = allColorEventsBeforeBeat[^1];
|
2023-08-12 03:30:03 +00:00
|
|
|
BackgroundColor(lastEvent.beat, lastEvent.length, lastEvent["colorA"], lastEvent["colorB"], lastEvent["ease"]);
|
|
|
|
}
|
2024-01-06 20:08:22 +00:00
|
|
|
var allAltFaceEventsBeforeBeat = allEventsBeforeBeat.FindAll(x => x.datamodel == "rhythmTweezers/altSmile");
|
|
|
|
VegetableAnimator.SetBool("UseAltSmile", allAltFaceEventsBeforeBeat.Count % 2 == 1);
|
2022-02-17 12:11:06 +00:00
|
|
|
}
|
|
|
|
|
2023-06-10 19:13:29 +00:00
|
|
|
public static void PreNoPeeking(double beat, float length, int type)
|
2023-05-29 20:09:34 +00:00
|
|
|
{
|
|
|
|
if (GameManager.instance.currentGame == "rhythmTweezers")
|
|
|
|
{
|
2023-06-03 14:51:30 +00:00
|
|
|
instance.NoPeeking(beat, length, type);
|
2023-05-29 20:09:34 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
queuedPeeks.Add(new QueuedPeek()
|
|
|
|
{
|
|
|
|
beat = beat,
|
2023-06-03 14:51:30 +00:00
|
|
|
length = length,
|
|
|
|
type = type
|
2023-05-29 20:09:34 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-10 19:13:29 +00:00
|
|
|
public void NoPeeking(double beat, float length, int type)
|
2023-05-29 20:09:34 +00:00
|
|
|
{
|
2023-06-03 14:51:30 +00:00
|
|
|
NoPeekingSign spawnedNoPeekingSign = Instantiate(noPeekingRef, transform);
|
|
|
|
spawnedNoPeekingSign.gameObject.SetActive(true);
|
|
|
|
spawnedNoPeekingSign.Init(beat, length, type);
|
2023-05-29 20:09:34 +00:00
|
|
|
}
|
|
|
|
|
2022-02-09 03:58:25 +00:00
|
|
|
private void Update()
|
|
|
|
{
|
2023-05-29 20:09:34 +00:00
|
|
|
if (Conductor.instance.isPlaying && !Conductor.instance.isPaused)
|
2022-02-09 10:29:09 +00:00
|
|
|
{
|
2023-05-29 20:09:34 +00:00
|
|
|
if (passedTurns.Count > 0)
|
|
|
|
{
|
|
|
|
foreach (var turn in passedTurns)
|
|
|
|
{
|
2023-06-28 04:51:53 +00:00
|
|
|
PassTurnStandalone(turn);
|
2023-05-29 20:09:34 +00:00
|
|
|
}
|
|
|
|
passedTurns.Clear();
|
|
|
|
}
|
|
|
|
if (queuedPeeks.Count > 0)
|
|
|
|
{
|
|
|
|
foreach (var peek in queuedPeeks)
|
|
|
|
{
|
2023-06-03 14:51:30 +00:00
|
|
|
NoPeeking(peek.beat, peek.length, peek.type);
|
2023-05-29 20:09:34 +00:00
|
|
|
}
|
|
|
|
queuedPeeks.Clear();
|
|
|
|
}
|
2022-02-09 10:29:09 +00:00
|
|
|
}
|
2023-08-12 03:30:03 +00:00
|
|
|
|
|
|
|
BackgroundColorUpdate();
|
2022-02-09 10:29:09 +00:00
|
|
|
}
|
|
|
|
|
2023-06-28 04:51:53 +00:00
|
|
|
public override void OnGameSwitch(double beat)
|
2022-02-09 10:29:09 +00:00
|
|
|
{
|
2023-06-28 04:51:53 +00:00
|
|
|
if (Conductor.instance.isPlaying && !Conductor.instance.isPaused)
|
|
|
|
{
|
|
|
|
if (queuedIntervals.Count > 0)
|
|
|
|
{
|
|
|
|
foreach (var interval in queuedIntervals)
|
|
|
|
{
|
|
|
|
SetIntervalStart(interval.beat, beat, interval.interval, interval.autoPassTurn);
|
|
|
|
}
|
|
|
|
queuedIntervals.Clear();
|
|
|
|
}
|
|
|
|
}
|
2024-01-06 20:08:22 +00:00
|
|
|
PersistBlocks(beat);
|
2022-02-09 10:29:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private void ResetVegetable()
|
|
|
|
{
|
2022-02-14 18:23:24 +00:00
|
|
|
// If the tweezers happen to be holding a hair, drop it immediately so it can be destroyed below.
|
2023-06-28 04:51:53 +00:00
|
|
|
currentTweezers?.DropHeldHair();
|
2022-02-14 18:23:24 +00:00
|
|
|
|
2022-02-09 10:29:09 +00:00
|
|
|
foreach (Transform t in HairsHolder.transform)
|
|
|
|
{
|
2022-02-10 15:29:53 +00:00
|
|
|
GameObject.Destroy(t.gameObject);
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach (Transform t in DroppedHairsHolder.transform)
|
|
|
|
{
|
|
|
|
GameObject.Destroy(t.gameObject);
|
2022-02-09 10:29:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
VegetableAnimator.Play("Idle", 0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
private void StopTransitionIfActive()
|
|
|
|
{
|
|
|
|
if (transitioning)
|
|
|
|
{
|
|
|
|
if (transitionTween != null)
|
2023-01-19 02:31:08 +00:00
|
|
|
{
|
|
|
|
transitionTween.Complete(true);
|
|
|
|
transitionTween.Kill();
|
|
|
|
}
|
2022-02-09 10:29:09 +00:00
|
|
|
}
|
2022-02-08 14:26:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|