using System.Collections; using System.Collections.Generic; using UnityEngine; using System; using Starpelly; using DG.Tweening; using HeavenStudio.Util; namespace HeavenStudio.Games { using Scripts_RhythmTweezers; public class RhythmTweezers : Minigame { public enum VegetableType { Onion, Potato } [Header("References")] public Transform VegetableHolder; public SpriteRenderer Vegetable; public SpriteRenderer VegetableDupe; public Animator VegetableAnimator; public SpriteRenderer bg; public Tweezers Tweezers; public GameObject hairBase; public GameObject longHairBase; public GameObject pluckedHairBase; public GameObject HairsHolder; public GameObject DroppedHairsHolder; [NonSerialized] public int hairsLeft = 0; [Header("Variables")] public float beatInterval = 4f; float intervalStartBeat; bool intervalStarted; public float tweezerBeatOffset = 0f; [Header("Sprites")] public Sprite pluckedHairSprite; public Sprite missedHairSprite; public Sprite onionSprite; public Sprite potatoSprite; [NonSerialized] public int eyeSize = 0; Tween transitionTween; bool transitioning = false; Tween bgColorTween; 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; } } private static Color _defaultBgColor; public static Color defaultBgColor { get { ColorUtility.TryParseHtmlString("#D8FFC1", out _defaultBgColor); return _defaultBgColor; } } public static RhythmTweezers instance { get; set; } private void Awake() { instance = this; } public void SpawnHair(float beat) { // End transition early if the next hair is a lil early. StopTransitionIfActive(); // If interval hasn't started, assume this is the first hair of the interval. if (!intervalStarted) { SetIntervalStart(beat, beatInterval); } Jukebox.PlayOneShotGame("rhythmTweezers/shortAppear", beat); Hair hair = Instantiate(hairBase, HairsHolder.transform).GetComponent(); hair.gameObject.SetActive(true); hair.GetComponent().Play("SmallAppear", 0, 0); float rot = -58f + 116 * Mathp.Normalize(beat, intervalStartBeat, intervalStartBeat + beatInterval - 1f); hair.transform.eulerAngles = new Vector3(0, 0, rot); hair.createBeat = beat; hairsLeft++; } public void SpawnLongHair(float beat) { StopTransitionIfActive(); if (!intervalStarted) { SetIntervalStart(beat, beatInterval); } Jukebox.PlayOneShotGame("rhythmTweezers/longAppear", beat); LongHair hair = Instantiate(longHairBase, HairsHolder.transform).GetComponent(); hair.gameObject.SetActive(true); hair.GetComponent().Play("LongAppear", 0, 0); float rot = -58f + 116 * Mathp.Normalize(beat, intervalStartBeat, intervalStartBeat + beatInterval - 1f); hair.transform.eulerAngles = new Vector3(0, 0, rot); hair.createBeat = beat; hairsLeft++; } public void SetIntervalStart(float beat, float interval = 4f) { // Don't do these things if the interval was already started. if (!intervalStarted) { // End transition early if the interval starts a lil early. StopTransitionIfActive(); hairsLeft = 0; intervalStarted = true; } intervalStartBeat = beat; beatInterval = interval; } const float vegDupeOffset = 16.7f; public void NextVegetable(float beat, int type, Color onionColor, Color potatoColor) { transitioning = true; Jukebox.PlayOneShotGame("rhythmTweezers/register", beat); Sprite nextVeggieSprite = type == 0 ? onionSprite : potatoSprite; Color nextColor = type == 0 ? onionColor : potatoColor; VegetableDupe.sprite = nextVeggieSprite; VegetableDupe.color = nextColor; // Move both vegetables to the left by vegDupeOffset, then reset their positions. // On position reset, reset state of core vegetable. transitionTween = VegetableHolder.DOLocalMoveX(-vegDupeOffset, Conductor.instance.secPerBeat * 0.5f / Conductor.instance.musicSource.pitch) .OnComplete(() => { var holderPos = VegetableHolder.localPosition; VegetableHolder.localPosition = new Vector3(0f, holderPos.y, holderPos.z); Vegetable.sprite = nextVeggieSprite; Vegetable.color = nextColor; ResetVegetable(); transitioning = false; intervalStarted = false; }).SetEase(Ease.InOutSine); } 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; } public void ChangeBackgroundColor(Color color, float beats) { var seconds = Conductor.instance.secPerBeat * beats; if (bgColorTween != null) bgColorTween.Kill(true); if (seconds == 0) { bg.color = color; } else { bgColorTween = bg.DOColor(color, seconds); } } public void FadeBackgroundColor(Color start, Color end, float beats) { ChangeBackgroundColor(start, 0f); ChangeBackgroundColor(end, beats); } private void Update() { if (!Conductor.instance.isPlaying && !Conductor.instance.isPaused && intervalStarted) { StopTransitionIfActive(); ResetVegetable(); intervalStarted = false; } } private void LateUpdate() { // Set tweezer angle. var tweezerAngle = -180f; if (intervalStarted) { var tweezerTime = Conductor.instance.songPositionInBeats - beatInterval - tweezerBeatOffset; var unclampedAngle = -58f + 116 * Mathp.Normalize(tweezerTime, intervalStartBeat, intervalStartBeat + beatInterval - 1f); tweezerAngle = Mathf.Clamp(unclampedAngle, -180f, 180f); } Tweezers.transform.eulerAngles = new Vector3(0, 0, tweezerAngle); // Set tweezer to follow vegetable. var currentTweezerPos = Tweezers.transform.localPosition; var vegetablePos = Vegetable.transform.localPosition; var vegetableHolderPos = VegetableHolder.transform.localPosition; Tweezers.transform.localPosition = new Vector3(vegetableHolderPos.x, vegetablePos.y + 1f, currentTweezerPos.z); } private void ResetVegetable() { // If the tweezers happen to be holding a hair, drop it immediately so it can be destroyed below. Tweezers.DropHeldHair(); foreach (Transform t in HairsHolder.transform) { GameObject.Destroy(t.gameObject); } foreach (Transform t in DroppedHairsHolder.transform) { GameObject.Destroy(t.gameObject); } VegetableAnimator.Play("Idle", 0, 0); eyeSize = 0; } private void StopTransitionIfActive() { if (transitioning) { if (transitionTween != null) transitionTween.Kill(true); } } } }