// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; using System.Collections.Generic; using System.Linq; using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.UI; using osu.Game.Rulesets.Objects.Types; using OpenTK; using osu.Game.Rulesets.Catch.MathUtils; namespace osu.Game.Rulesets.Catch.Beatmaps { public class CatchBeatmapProcessor : BeatmapProcessor { public CatchBeatmapProcessor(IBeatmap beatmap) : base(beatmap) { } public override void PostProcess() { applyPositionOffsets(); initialiseHyperDash((List)Beatmap.HitObjects); base.PostProcess(); int index = 0; foreach (var obj in Beatmap.HitObjects.OfType()) obj.IndexInBeatmap = index++; } public const int RNG_SEED = 1337; private void applyPositionOffsets() { var rng = new FastRandom(RNG_SEED); // todo: HardRock displacement should be applied here foreach (var obj in Beatmap.HitObjects) { switch (obj) { case BananaShower bananaShower: foreach (var nested in bananaShower.NestedHitObjects) { ((BananaShower.Banana)nested).X = (float)rng.NextDouble(); rng.Next(); // osu!stable retrieved a random banana type rng.Next(); // osu!stable retrieved a random banana rotation rng.Next(); // osu!stable retrieved a random banana colour } break; case JuiceStream juiceStream: foreach (var nested in juiceStream.NestedHitObjects) { if (nested is TinyDroplet tinyDroplet) tinyDroplet.X = MathHelper.Clamp(tinyDroplet.X + rng.Next(-20, 20) / CatchPlayfield.BASE_WIDTH, 0, 1); else if (nested is Droplet) rng.Next(); // osu!stable retrieved a random droplet rotation } break; } } } private void initialiseHyperDash(List objects) { // todo: add difficulty adjust. double halfCatcherWidth = CatcherArea.CATCHER_SIZE * (objects.FirstOrDefault()?.Scale ?? 1) / CatchPlayfield.BASE_WIDTH / 2; int lastDirection = 0; double lastExcess = halfCatcherWidth; int objCount = objects.Count; for (int i = 0; i < objCount - 1; i++) { CatchHitObject currentObject = objects[i]; // not needed? // if (currentObject is TinyDroplet) continue; CatchHitObject nextObject = objects[i + 1]; // while (nextObject is TinyDroplet) // { // if (++i == objCount - 1) break; // nextObject = objects[i + 1]; // } int thisDirection = nextObject.X > currentObject.X ? 1 : -1; double timeToNext = nextObject.StartTime - ((currentObject as IHasEndTime)?.EndTime ?? currentObject.StartTime) - 4; double distanceToNext = Math.Abs(nextObject.X - currentObject.X) - (lastDirection == thisDirection ? lastExcess : halfCatcherWidth); if (timeToNext * CatcherArea.Catcher.BASE_SPEED < distanceToNext) { currentObject.HyperDashTarget = nextObject; lastExcess = halfCatcherWidth; } else { //currentObject.DistanceToHyperDash = timeToNext - distanceToNext; lastExcess = MathHelper.Clamp(timeToNext - distanceToNext, 0, halfCatcherWidth); } lastDirection = thisDirection; } } } }