// Copyright (c) 2007-2017 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.Objects.Types; using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Replays; using osu.Game.Users; namespace osu.Game.Rulesets.Taiko.Replays { public class TaikoAutoGenerator : AutoGenerator { private const double swell_hit_speed = 50; public TaikoAutoGenerator(Beatmap beatmap) : base(beatmap) { Replay = new Replay { User = new User { Username = @"Autoplay", } }; } protected Replay Replay; protected List Frames => Replay.Frames; public override Replay Generate() { bool hitButton = true; Frames.Add(new ReplayFrame(-100000, null, null, ReplayButtonState.None)); Frames.Add(new ReplayFrame(Beatmap.HitObjects[0].StartTime - 1000, null, null, ReplayButtonState.None)); for (int i = 0; i < Beatmap.HitObjects.Count; i++) { TaikoHitObject h = Beatmap.HitObjects[i]; ReplayButtonState button; IHasEndTime endTimeData = h as IHasEndTime; double endTime = endTimeData?.EndTime ?? h.StartTime; Swell swell = h as Swell; DrumRoll drumRoll = h as DrumRoll; Hit hit = h as Hit; if (swell != null) { int d = 0; int count = 0; int req = swell.RequiredHits; double hitRate = Math.Min(swell_hit_speed, swell.Duration / req); for (double j = h.StartTime; j < endTime; j += hitRate) { switch (d) { default: case 0: button = ReplayButtonState.Left1; break; case 1: button = ReplayButtonState.Right1; break; case 2: button = ReplayButtonState.Left2; break; case 3: button = ReplayButtonState.Right2; break; } Frames.Add(new ReplayFrame(j, null, null, button)); d = (d + 1) % 4; if (++count == req) break; } } else if (drumRoll != null) { foreach (var tick in drumRoll.NestedHitObjects.OfType()) { Frames.Add(new ReplayFrame(tick.StartTime, null, null, hitButton ? ReplayButtonState.Left1 : ReplayButtonState.Left2)); hitButton = !hitButton; } } else if (hit != null) { if (hit is CentreHit) { if (h.IsStrong) button = ReplayButtonState.Right1 | ReplayButtonState.Right2; else button = hitButton ? ReplayButtonState.Right1 : ReplayButtonState.Right2; } else { if (h.IsStrong) button = ReplayButtonState.Left1 | ReplayButtonState.Left2; else button = hitButton ? ReplayButtonState.Left1 : ReplayButtonState.Left2; } Frames.Add(new ReplayFrame(h.StartTime, null, null, button)); } else throw new InvalidOperationException("Unknown hit object type."); Frames.Add(new ReplayFrame(endTime + KEY_UP_DELAY, null, null, ReplayButtonState.None)); if (i < Beatmap.HitObjects.Count - 1) { double waitTime = Beatmap.HitObjects[i + 1].StartTime - 1000; if (waitTime > endTime) Frames.Add(new ReplayFrame(waitTime, null, null, ReplayButtonState.None)); } hitButton = !hitButton; } return Replay; } } }