diff --git a/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapConverter.cs index 1fc2db53fa..aa095a1dda 100644 --- a/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapConverter.cs +++ b/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapConverter.cs @@ -44,7 +44,10 @@ namespace osu.Game.Modes.Taiko.Beatmaps IHasRepeats repeatsData = original as IHasRepeats; IHasEndTime endTimeData = original as IHasEndTime; - bool strong = ((original.Sample?.Type ?? SampleType.None) & SampleType.Finish) > 0; + // Old osu! used hit sounding to determine various hit type information + SampleType sample = original.Sample?.Type ?? SampleType.None; + + bool strong = (sample & SampleType.Finish) > 0; if (distanceData != null) { @@ -71,11 +74,14 @@ namespace osu.Game.Modes.Taiko.Beatmaps }; } + HitType type = (sample & ~(SampleType.Finish | SampleType.Normal)) == 0 ? HitType.Centre : HitType.Rim; + return new Hit { StartTime = original.StartTime, Sample = original.Sample, - IsStrong = strong + IsStrong = strong, + Type = type }; } } diff --git a/osu.Game.Modes.Taiko/LegacyTaikoReplay.cs b/osu.Game.Modes.Taiko/LegacyTaikoReplay.cs new file mode 100644 index 0000000000..0b59c9ddd4 --- /dev/null +++ b/osu.Game.Modes.Taiko/LegacyTaikoReplay.cs @@ -0,0 +1,47 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Collections.Generic; +using System.IO; +using osu.Framework.Input; +using osu.Game.Input.Handlers; +using OpenTK.Input; + +namespace osu.Game.Modes.Taiko +{ + public class LegacyTaikoReplay : LegacyReplay + { + protected LegacyTaikoReplay() + { + } + + public LegacyTaikoReplay(StreamReader reader) + : base(reader) + { + } + + public override ReplayInputHandler CreateInputHandler() => new LegacyTaikoReplayInputHandler(Frames); + + private class LegacyTaikoReplayInputHandler : LegacyReplayInputHandler + { + public LegacyTaikoReplayInputHandler(List replayContent) + : base(replayContent) + { + } + + public override List GetPendingStates() => new List + { + new InputState + { + Keyboard = new ReplayKeyboardState(new List(new[] + { + CurrentFrame?.MouseRight1 == true ? Key.F : Key.Unknown, + CurrentFrame?.MouseRight2 == true ? Key.J : Key.Unknown, + CurrentFrame?.MouseLeft1 == true ? Key.D : Key.Unknown, + CurrentFrame?.MouseLeft2 == true ? Key.K : Key.Unknown + })) + } + }; + } + } +} diff --git a/osu.Game.Modes.Taiko/Mods/TaikoMod.cs b/osu.Game.Modes.Taiko/Mods/TaikoMod.cs index c929ebffdd..007187d81b 100644 --- a/osu.Game.Modes.Taiko/Mods/TaikoMod.cs +++ b/osu.Game.Modes.Taiko/Mods/TaikoMod.cs @@ -1,7 +1,10 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Game.Beatmaps; using osu.Game.Modes.Mods; +using osu.Game.Modes.Scoring; +using osu.Game.Modes.Taiko.Objects; namespace osu.Game.Modes.Taiko.Mods { @@ -61,4 +64,12 @@ namespace osu.Game.Modes.Taiko.Mods { } + + public class TaikoModAutoplay : ModAutoplay + { + protected override Score CreateReplayScore(Beatmap beatmap) => new Score + { + Replay = new TaikoAutoReplay(beatmap) + }; + } } diff --git a/osu.Game.Modes.Taiko/Objects/Hit.cs b/osu.Game.Modes.Taiko/Objects/Hit.cs index ad8d07d901..0ba07028fd 100644 --- a/osu.Game.Modes.Taiko/Objects/Hit.cs +++ b/osu.Game.Modes.Taiko/Objects/Hit.cs @@ -8,6 +8,11 @@ namespace osu.Game.Modes.Taiko.Objects { public class Hit : TaikoHitObject { + /// + /// Whether this hit is a centre-hit or a rim-hit. + /// + public HitType Type; + /// /// The hit window that results in a "GREAT" hit. /// diff --git a/osu.Game.Modes.Taiko/Objects/HitType.cs b/osu.Game.Modes.Taiko/Objects/HitType.cs new file mode 100644 index 0000000000..6e8e147d75 --- /dev/null +++ b/osu.Game.Modes.Taiko/Objects/HitType.cs @@ -0,0 +1,14 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +namespace osu.Game.Modes.Taiko.Objects +{ + /// + /// Describes whether a hit is a centre-hit or a rim-hit. + /// + public enum HitType + { + Centre, + Rim + } +} diff --git a/osu.Game.Modes.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Modes.Taiko/Scoring/TaikoScoreProcessor.cs index 2ab31c5efb..ad9392a72e 100644 --- a/osu.Game.Modes.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Modes.Taiko/Scoring/TaikoScoreProcessor.cs @@ -119,6 +119,15 @@ namespace osu.Game.Modes.Taiko.Scoring { } + public override Score CreateScore() => new TaikoScore + { + TotalScore = TotalScore, + Combo = Combo, + MaxCombo = HighestCombo, + Accuracy = Accuracy, + Health = Health, + }; + protected override void ComputeTargets(Beatmap beatmap) { double hpMultiplierNormal = 1 / (hp_hit_great * beatmap.HitObjects.FindAll(o => o is Hit).Count * BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.Difficulty.DrainRate, 0.5, 0.75, 0.98)); diff --git a/osu.Game.Modes.Taiko/TaikoAutoReplay.cs b/osu.Game.Modes.Taiko/TaikoAutoReplay.cs new file mode 100644 index 0000000000..ba121e0968 --- /dev/null +++ b/osu.Game.Modes.Taiko/TaikoAutoReplay.cs @@ -0,0 +1,121 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Modes.Taiko.Objects; +using osu.Game.Modes.Objects.Types; +using osu.Game.Beatmaps; + +namespace osu.Game.Modes.Taiko +{ + public class TaikoAutoReplay : LegacyTaikoReplay + { + private readonly Beatmap beatmap; + + public TaikoAutoReplay(Beatmap beatmap) + { + this.beatmap = beatmap; + + createAutoReplay(); + } + + private void createAutoReplay() + { + bool hitButton = true; + + Frames.Add(new LegacyReplayFrame(-100000, 320, 240, LegacyButtonState.None)); + Frames.Add(new LegacyReplayFrame(beatmap.HitObjects[0].StartTime - 1000, 320, 240, LegacyButtonState.None)); + + for (int i = 0; i < beatmap.HitObjects.Count; i++) + { + TaikoHitObject h = beatmap.HitObjects[i]; + + LegacyButtonState button; + + IHasEndTime endTimeData = h as IHasEndTime; + double endTime = endTimeData?.EndTime ?? h.StartTime; + + Swell sp = h as Swell; + if (sp != null) + { + int d = 0; + int count = 0; + int req = sp.RequiredHits; + double hitRate = sp.Duration / req; + for (double j = h.StartTime; j < endTime; j += hitRate) + { + switch (d) + { + default: + button = LegacyButtonState.Left1; + break; + case 1: + button = LegacyButtonState.Right1; + break; + case 2: + button = LegacyButtonState.Left2; + break; + case 3: + button = LegacyButtonState.Right2; + break; + } + + Frames.Add(new LegacyReplayFrame(j, 0, 0, button)); + d = (d + 1) % 4; + if (++count > req) + break; + } + } + else if (h is DrumRoll) + { + DrumRoll d = h as DrumRoll; + + double delay = d.TickTimeDistance; + + double time = d.StartTime; + + for (int j = 0; j < d.TotalTicks; j++) + { + Frames.Add(new LegacyReplayFrame((int)time, 0, 0, hitButton ? LegacyButtonState.Left1 : LegacyButtonState.Left2)); + time += delay; + hitButton = !hitButton; + } + } + else + { + Hit hit = h as Hit; + + if (hit.Type == HitType.Centre) + { + if (h.IsStrong) + button = LegacyButtonState.Right1 | LegacyButtonState.Right2; + else + button = hitButton ? LegacyButtonState.Right1 : LegacyButtonState.Right2; + } + else + { + if (h.IsStrong) + button = LegacyButtonState.Left1 | LegacyButtonState.Left2; + else + button = hitButton ? LegacyButtonState.Left1 : LegacyButtonState.Left2; + } + + Frames.Add(new LegacyReplayFrame(h.StartTime, 0, 0, button)); + } + + Frames.Add(new LegacyReplayFrame(endTime + 1, 0, 0, LegacyButtonState.None)); + + if (i < beatmap.HitObjects.Count - 1) + { + double waitTime = beatmap.HitObjects[i + 1].StartTime - 1000; + if (waitTime > endTime) + Frames.Add(new LegacyReplayFrame(waitTime, 0, 0, LegacyButtonState.None)); + } + + hitButton = !hitButton; + } + + //Player.currentScore.Replay = InputManager.ReplayScore.Replay; + //Player.currentScore.PlayerName = "mekkadosu!"; + } + } +} \ No newline at end of file diff --git a/osu.Game.Modes.Taiko/TaikoRuleset.cs b/osu.Game.Modes.Taiko/TaikoRuleset.cs index ce7e756e30..1b3c3fc0eb 100644 --- a/osu.Game.Modes.Taiko/TaikoRuleset.cs +++ b/osu.Game.Modes.Taiko/TaikoRuleset.cs @@ -65,7 +65,7 @@ namespace osu.Game.Modes.Taiko { Mods = new Mod[] { - new ModAutoplay(), + new TaikoModAutoplay(), new ModCinema(), }, }, diff --git a/osu.Game.Modes.Taiko/TaikoScore.cs b/osu.Game.Modes.Taiko/TaikoScore.cs new file mode 100644 index 0000000000..2d5c3e750b --- /dev/null +++ b/osu.Game.Modes.Taiko/TaikoScore.cs @@ -0,0 +1,13 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Modes.Scoring; +using System.IO; + +namespace osu.Game.Modes.Taiko +{ + public class TaikoScore : Score + { + public override Replay CreateLegacyReplayFrom(StreamReader reader) => new LegacyTaikoReplay(reader); + } +} diff --git a/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj b/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj index 0f99371bad..4c8784b6da 100644 --- a/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj +++ b/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj @@ -52,6 +52,7 @@ + @@ -72,11 +73,14 @@ + + +