using System.Collections; using System.Collections.Generic; using UnityEngine; using HeavenStudio.Util; using HeavenStudio.Games.Scripts_TotemClimb; using Jukebox; using System; namespace HeavenStudio.Games.Loaders { using static Minigames; public static class TotemClimbLoader { public static Minigame AddGame(EventCaller eventCaller) { return new Minigame("totemClimb", "Totem Climb", "FFFFFF", false, false, new() { new("start", "Start Jumping") { preFunction = delegate { if (eventCaller.currentEntity["cue"]) TotemClimb.StartCueIn(eventCaller.currentEntity.beat); }, parameters = new List() { new("cue", true, "Cue-In"), new("hide", false, "Hide Fence") } }, new("triple", "Triple Jumping") { preFunction = delegate { var e = eventCaller.currentEntity; TotemClimb.TripleJumpSound(e.beat, e.length, e["enter"], e["exit"]); }, defaultLength = 2f, resizable = true, parameters = new() { new("enter", true, "Enter Cue Sound"), new("exit", true, "Exit Cue Sound"), } }, new("high", "High Jump") { preFunction = delegate { double beat = eventCaller.currentEntity.beat; MultiSound.Play(new MultiSound.Sound[] { new MultiSound.Sound("count-ins/ready1", beat - 2f), new MultiSound.Sound("count-ins/ready2", beat - 1f), }, false, true); }, defaultLength = 4f }, new("startCue", "Normal Jump Cue") { preFunction = delegate { TotemClimb.StartCueIn(eventCaller.currentEntity.beat + 2); }, defaultLength = 2f }, new("tripleCue", "Triple Jump Cue") { preFunction = delegate { TotemClimb.TripleCueIn(eventCaller.currentEntity.beat + 2); }, defaultLength = 2f }, new("bird", "Bird") { function = delegate { var e = eventCaller.currentEntity; TotemClimb.instance.SpawnBird(e["speed"], (TotemClimb.BirdType)e["type"] == TotemClimb.BirdType.Penguin, e["amount"]); }, parameters = new List() { new("speed", new EntityTypes.Float(1, 100, 3), "Speed Multiplier"), new("type", TotemClimb.BirdType.KingFisher, "Type"), new("amount", new EntityTypes.Integer(1, 3, 1), "Amount") } }, new("above", "Fences End") { }, new("stop", "Stop Jumping") { parameters = new List() { new("anim", true, "Has Ending Animation") } }, new("bop", "Bop") { function = delegate { TotemClimb.instance.Bop(eventCaller.currentEntity.beat, eventCaller.currentEntity.length, eventCaller.currentEntity.beat); }, resizable = true, defaultLength = 4f } }); } } } namespace HeavenStudio.Games { public class TotemClimb : Minigame { public enum BirdType { KingFisher, Penguin } [Header("Components")] [SerializeField] private Transform _cameraTransform; [SerializeField] private Transform _scrollTransform; [SerializeField] private TCJumper _jumper; [SerializeField] private TCTotemManager _totemManager; [SerializeField] private TCBirdManager _birdManager; [Header("Properties")] [SerializeField] private float _scrollSpeedX = 3.838f; [SerializeField] private float _scrollSpeedY = 1.45f; private double _startBeat = double.MaxValue; public double StartBeat => _startBeat; private double _endBeat = double.MaxValue; public double EndBeat => _endBeat; private double _pillarEndBeat = double.MaxValue; public double PillarEndBeat => _pillarEndBeat; private bool _useEndTotem = false; public bool UseEndTotem => _useEndTotem; [NonSerialized] public List _tripleEvents = new(); [NonSerialized] public List _highJumpEvents = new(); public static TotemClimb instance; private void Awake() { instance = this; } public void SpawnBird(float speed, bool penguin, int amount) { _birdManager.AddBird(speed, penguin, amount); } public override void OnGameSwitch(double beat) { CalculateStartAndEndBeat(beat); GetHighJumpEvents(); GetTripleEvents(); HandleBopsOnStart(beat); _totemManager.InitBeats(_startBeat, _endBeat, _useEndTotem); _jumper.InitPath(_startBeat, beat); } public override void OnPlay(double beat) { var allGameSwitches = EventCaller.GetAllInGameManagerList("gameManager", new string[] { "switchGame" }).FindAll(x => x.beat <= beat && x.datamodel is "gameManager/switchGame/totemClimb"); double lastGameSwitchBeat = 0; if (allGameSwitches.Count > 0) lastGameSwitchBeat = allGameSwitches[^1].beat; CalculateStartAndEndBeat(lastGameSwitchBeat); GetHighJumpEvents(); GetTripleEvents(); HandleBopsOnStart(beat); _totemManager.InitBeats(_startBeat, _endBeat, _useEndTotem); _jumper.InitPath(_startBeat, beat); } private void CalculateStartAndEndBeat(double beat) { var nextGameSwitches = EventCaller.GetAllInGameManagerList("gameManager", new string[] { "switchGame" }).FindAll(x => x.beat > beat && x.datamodel != "gameManager/switchGame/totemClimb"); double nextGameSwitchBeat = double.MaxValue; if (nextGameSwitches.Count > 0) { nextGameSwitchBeat = nextGameSwitches[0].beat; } var allStarts = EventCaller.GetAllInGameManagerList("totemClimb", new string[] { "start" }).FindAll(x => x.beat >= beat && x.beat < nextGameSwitchBeat); if (allStarts.Count == 0) return; _startBeat = allStarts[0].beat; BeatAction.New(this, new() { new(_startBeat - 1, delegate { _jumper.StartJumping(_startBeat - 1); }) }); var allPillarEnds = EventCaller.GetAllInGameManagerList("totemClimb", new string[] { "above" }).FindAll(x => x.beat >= _startBeat && x.beat < nextGameSwitchBeat); if (allPillarEnds.Count > 0) _pillarEndBeat = allPillarEnds[0].beat; var allStops = EventCaller.GetAllInGameManagerList("totemClimb", new string[] { "stop" }).FindAll(x => x.beat > _startBeat && x.beat < nextGameSwitchBeat); if (allStops.Count == 0) return; _endBeat = allStops[0].beat; _useEndTotem = allStops[0]["anim"]; } private void HandleBopsOnStart(double beat) { var e = EventCaller.GetAllInGameManagerList("totemClimb", new string[] { "bop" }).Find(x => x.beat < beat && x.beat + x.length > beat); if (e == null) return; Bop(e.beat, e.length, beat); } private void GetHighJumpEvents() { var highs = EventCaller.GetAllInGameManagerList("totemClimb", new string[] { "high" }).FindAll(x => x.beat >= _startBeat && x.beat < _endBeat); if (highs.Count == 0) return; highs.Sort((x, y) => x.beat.CompareTo(y.beat)); var tempHighs = new List(); double goodAfterBeat = _startBeat; foreach (var h in highs) { if (h.beat >= goodAfterBeat && IsOnBeat(_startBeat, h.beat)) { tempHighs.Add(h); goodAfterBeat = h.beat + 4; } } _highJumpEvents = tempHighs; } private void GetTripleEvents() { var triples = EventCaller.GetAllInGameManagerList("totemClimb", new string[] { "triple" }).FindAll(x => x.beat >= _startBeat && x.beat + x.length <= _endBeat); if (triples.Count == 0) return; triples.Sort((x, y) => x.beat.CompareTo(y.beat)); var tempTriples = new List(); double lastLengthBeat = _startBeat; foreach (var t in triples) { if (t.beat >= lastLengthBeat && IsOnBeat(_startBeat, t.beat)) { if (_highJumpEvents.Find(x => x.beat + 4f > t.beat && x.beat + 4 < t.beat + t.length + 4) != null) continue; tempTriples.Add(t); lastLengthBeat = t.beat + t.length; } } _tripleEvents = tempTriples; } private void Update() { var cond = Conductor.instance; ScrollUpdate(cond); } public void BopTotemAtBeat(double beat) { _totemManager.BopTotemAtBeat(beat); } public Transform GetJumperPointAtBeat(double beat) { return _totemManager.GetJumperPointAtBeat(beat); } public Transform GetJumperFrogPointAtBeat(double beat, int part) { return _totemManager.GetJumperFrogPointAtBeat(beat, part); } public Transform GetDragonPointAtBeat(double beat) { return _totemManager.GetHighJumperPointAtBeat(beat); } public void HoldDragonAtBeat(double beat) { _totemManager.HoldDragonAtBeat(beat); } public void ReleaseDragonAtBeat(double beat) { _totemManager.ReleaseDragonAtBeat(beat); } public void FallFrogAtBeat(double beat, int part) { _totemManager.FallFrogAtBeat(beat, part); } public void Bop(double beat, float length, double callBeat) { List actions = new(); for (int i = 0; i < length; i++) { double bopBeat = beat + i; if (bopBeat < callBeat) continue; actions.Add(new(bopBeat, delegate { BopJumper(bopBeat); })); } if (actions.Count > 0) BeatAction.New(this, actions); } private void BopJumper(double beat) { if (beat >= _startBeat && beat < _endBeat) return; _jumper.Bop(); } private void ScrollUpdate(Conductor cond) { if (_startBeat == double.MaxValue) return; double beatDistance = _endBeat - _startBeat; float normalizedBeat = Mathf.Clamp(cond.GetPositionFromBeat(_startBeat, 1), 0f, (float)beatDistance); if (IsHighBeatBasedOnStart(normalizedBeat)) { var h = GetHighJumpAtBeatBasedOnStart(normalizedBeat); if (h != null) { double highBeat = h.beat - _startBeat; if (normalizedBeat >= highBeat + 2) { normalizedBeat = Mathf.Clamp(normalizedBeat - 2 + (cond.GetPositionFromBeat(h.beat + 2, 2) * 2), (float)highBeat, (float)highBeat + 4); } else if (normalizedBeat >= highBeat) { normalizedBeat = Mathf.Clamp(normalizedBeat, 0f, (float)highBeat); } } } _scrollTransform.localPosition = new Vector3(normalizedBeat * _scrollSpeedX, normalizedBeat * _scrollSpeedY); _cameraTransform.localPosition = new Vector3(_scrollTransform.localPosition.x * -2, _scrollTransform.localPosition.y * -2); } private static bool IsOnBeat(double startBeat, double targetBeat) { return (targetBeat - startBeat) % 1 == 0; } public bool IsTripleBeat(double beat) { if (_tripleEvents.Count == 0) return false; return _tripleEvents.Find(x => beat >= x.beat && beat < x.beat + x.length) != null; } public bool IsHighBeat(double beat) { if (_highJumpEvents.Count == 0) return false; return _highJumpEvents.Find(x => beat >= x.beat && beat < x.beat + 4) != null; } public bool IsHighBeatBasedOnStart(double beat) { if (_highJumpEvents.Count == 0) return false; return _highJumpEvents.Find(x => beat >= x.beat - _startBeat && beat < x.beat - _startBeat + 4) != null; } public RiqEntity GetHighJumpAtBeatBasedOnStart(double beat) { if (_highJumpEvents.Count == 0) return null; return _highJumpEvents.Find(x => beat >= x.beat - _startBeat && beat < x.beat - _startBeat + 4); } public bool IsTripleOrHighBeat(double beat) { return IsHighBeat(beat) || IsTripleBeat(beat); } public void DoEndTotemEvents(double beat) { SoundByte.PlayOneShotGame("totemClimb/finallanding", beat); _totemManager.EndTotemAnimator.DoScaledAnimationAsync("Land", 0.5f); SoundByte.PlayOneShotGame("totemClimb/openwings", beat + 1); BeatAction.New(this, new() { new(beat + 1, delegate { _totemManager.EndTotemAnimator.DoScaledAnimationAsync("OpenWings", 0.5f); }) }); } public Transform EndJumperPoint => _totemManager.EndJumperPoint; public static void StartCueIn(double beat) { MultiSound.Play(new MultiSound.Sound[] { new("totemClimb/beatchange", beat - 2), new("totemClimb/beatchange", beat - 1), }, true, true); } public static void TripleCueIn(double beat) { MultiSound.Play(new MultiSound.Sound[] { new("totemClimb/beatchange", beat - 2), new("totemClimb/beatchange", beat - 1.5), new("totemClimb/beatchange", beat - 1), }, true, true); } public static void TripleJumpSound(double beat, float length, bool enterSound, bool exitSound) { if (!enterSound && !exitSound) return; List triplesGlobal = new(); List highsGlobal = new(); length = Mathf.Max(length, 2f); List soundsEnter = new() { new("totemClimb/beatchange", beat - 2), new("totemClimb/beatchange", beat - 1.5f), new("totemClimb/beatchange", beat - 1f), }; List soundsToPlay = new(); var allGameSwitches = EventCaller.GetAllInGameManagerList("gameManager", new string[] { "switchGame" }).FindAll(x => x.beat <= beat && x.datamodel is "gameManager/switchGame/totemClimb"); double lastGameSwitchBeat = 0; if (allGameSwitches.Count > 0) lastGameSwitchBeat = allGameSwitches[^1].beat; SetUpEvents(lastGameSwitchBeat); if (triplesGlobal.Count == 0) return; bool doEnterSound = true; double checkBeatEnter = beat - 1; while (IsHighBeat(checkBeatEnter)) { checkBeatEnter -= 4; if (IsTripleBeat(checkBeatEnter)) { doEnterSound = false; } } if (doEnterSound && enterSound) soundsToPlay.AddRange(soundsEnter); bool doExitSound = true; double checkBeatExit = beat + length; while (IsHighBeat(checkBeatExit)) { checkBeatExit += 4; if (IsTripleBeat(checkBeatExit)) { doExitSound = false; } } List soundsExit = new() { new("totemClimb/beatchange", checkBeatExit - 2), new("totemClimb/beatchange", checkBeatExit - 1), }; if (doExitSound && exitSound) soundsToPlay.AddRange(soundsExit); if (soundsToPlay.Count > 0) MultiSound.Play(soundsToPlay.ToArray(), true, true); void SetUpEvents(double beat) { double startBeat = double.MaxValue; double endBeat = double.MaxValue; var nextGameSwitches = EventCaller.GetAllInGameManagerList("gameManager", new string[] { "switchGame" }).FindAll(x => x.beat > beat && x.datamodel != "gameManager/switchGame/totemClimb"); double nextGameSwitchBeat = double.MaxValue; if (nextGameSwitches.Count > 0) { nextGameSwitchBeat = nextGameSwitches[0].beat; } var allStarts = EventCaller.GetAllInGameManagerList("totemClimb", new string[] { "start" }).FindAll(x => x.beat >= beat && x.beat < nextGameSwitchBeat); if (allStarts.Count > 0) { startBeat = allStarts[0].beat; } var allStops = EventCaller.GetAllInGameManagerList("totemClimb", new string[] { "stop" }).FindAll(x => x.beat > startBeat && x.beat < nextGameSwitchBeat); if (allStops.Count > 0) { endBeat = allStops[0].beat; } var highs = EventCaller.GetAllInGameManagerList("totemClimb", new string[] { "high" }).FindAll(x => x.beat >= startBeat && x.beat < endBeat); if (highs.Count > 0) { highs.Sort((x, y) => x.beat.CompareTo(y.beat)); var tempHighs = new List(); double goodAfterBeat = startBeat; foreach (var h in highs) { if (h.beat >= goodAfterBeat && IsOnBeat(startBeat, h.beat)) { tempHighs.Add(h); goodAfterBeat = h.beat + 4; } } highsGlobal = tempHighs; } var triples = EventCaller.GetAllInGameManagerList("totemClimb", new string[] { "triple" }).FindAll(x => x.beat >= startBeat && x.beat + x.length <= endBeat); if (triples.Count == 0) return; triples.Sort((x, y) => x.beat.CompareTo(y.beat)); var tempTriples = new List(); double lastLengthBeat = startBeat; foreach (var t in triples) { if (t.beat >= lastLengthBeat && IsOnBeat(startBeat, t.beat)) { if (highsGlobal.Find(x => x.beat + 4f > t.beat && x.beat + 4 < t.beat + t.length + 4) != null) continue; tempTriples.Add(t); lastLengthBeat = t.beat + t.length; } } triplesGlobal = tempTriples; } bool IsTripleBeat(double beat) { if (triplesGlobal.Count == 0) return false; return triplesGlobal.Find(x => beat >= x.beat && beat < x.beat + x.length) != null; } bool IsHighBeat(double beat) { if (highsGlobal.Count == 0) return false; return highsGlobal.Find(x => beat >= x.beat && beat < x.beat + 4) != null; } } } }