From 426ca00516e61be0c4b1e35ec3c154e857931475 Mon Sep 17 00:00:00 2001 From: Hiviexd Date: Sun, 17 Nov 2024 17:48:16 +0100 Subject: [PATCH 01/15] Add osu!taiko mod `Simplified Rhythm` --- .../Mods/TaikoModSimplifiedRhythm.cs | 133 ++++++++++++++++++ osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 1 + 2 files changed, 134 insertions(+) create mode 100644 osu.Game.Rulesets.Taiko/Mods/TaikoModSimplifiedRhythm.cs diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModSimplifiedRhythm.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModSimplifiedRhythm.cs new file mode 100644 index 0000000000..14b819163b --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModSimplifiedRhythm.cs @@ -0,0 +1,133 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using System.Linq; +using osu.Framework.Bindables; +using osu.Framework.Localisation; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Configuration; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Taiko.Beatmaps; +using osu.Game.Rulesets.Taiko.Objects; + +namespace osu.Game.Rulesets.Taiko.Mods +{ + public class TaikoModSimplifiedRhythm : Mod, IApplicableToBeatmap + { + public override string Name => "Simplified Rhythm"; + public override string Acronym => "SR"; + public override double ScoreMultiplier => 0.6; + public override LocalisableString Description => "Simplify tricky rhythms!"; + public override ModType Type => ModType.DifficultyReduction; + + [SettingSource("One-third conversion", "Converts 1/3 snap to 1/2 snap.")] + public Bindable EnableOneThird { get; } = new BindableBool(false); + + [SettingSource("One-sixth conversion", "Converts 1/6 snap to 1/4 snap.")] + public Bindable EnableOneSixth { get; } = new BindableBool(true); + + [SettingSource("One-eighth conversion", "Converts 1/8 snap to 1/4 snap.")] + public Bindable EnableOneEighth { get; } = new BindableBool(false); + + public void ApplyToBeatmap(IBeatmap beatmap) + { + var taikoBeatmap = (TaikoBeatmap)beatmap; + var controlPointInfo = taikoBeatmap.ControlPointInfo; + List toRemove = []; + + // Snap conversions for rhythms + var snapConversions = new Dictionary() + { + { 8, 4 }, // 1/8 snap to 1/4 snap + { 6, 4 }, // 1/6 snap to 1/4 snap + { 3, 2 }, // 1/3 snap to 1/2 snap + }; + + double beatLength = controlPointInfo.TimingPointAt(0).BeatLength; + int patternStartIndex = 0; + bool inPattern = false; + + List hits = taikoBeatmap.HitObjects.Where(obj => obj is Hit).Cast().ToList(); + + foreach (var snapConversion in snapConversions) + { + // Skip processing if the corresponding conversion is disabled + if (!shouldProcessRhythm(snapConversion.Key)) + continue; + + for (int i = 0; i < hits.Count; i++) + { + double snapValue = i < hits.Count - 1 + ? getSnapBetweenNotes(controlPointInfo, hits[i], hits[i + 1]) + : 1; // No next note, default to a safe 1/1 snap + if (snapValue == snapConversion.Key) + { + if (!inPattern) + { + patternStartIndex = i; + } + inPattern = true; + } + // check if end of pattern or if we're on the last note + if ((inPattern && snapValue != snapConversion.Key) || i == hits.Count) + { + // End of the pattern + inPattern = false; + + // Iterate through the pattern + for (int j = patternStartIndex; j <= i; j++) + { + int currentHitPosition = j - patternStartIndex; + + if (snapConversion.Key == 8) + { + // 1/8: Remove the second note + if (currentHitPosition % 2 == 1) + { + toRemove.Add(hits[j]); + } + } + else + { + // 1/6 and 1/3: Adjust the second note and remove the third + if (currentHitPosition % 3 == 1) + { + hits[j].StartTime = hits[j - 1].StartTime + controlPointInfo.TimingPointAt(hits[j].StartTime).BeatLength / Convert.ToDouble(snapConversion.Value); + } + else if (currentHitPosition % 3 == 2) + { + toRemove.Add(hits[j]); + } + } + } + } + } + + // Remove queued notes + taikoBeatmap.HitObjects = taikoBeatmap.HitObjects.Except(toRemove).ToList(); + } + } + + private int getSnapBetweenNotes(ControlPointInfo controlPointInfo, Hit currentNote, Hit nextNote) + { + double gapMs = Math.Max(currentNote.StartTime, nextNote.StartTime) - Math.Min(currentNote.StartTime, nextNote.StartTime); + var currentTimingPoint = controlPointInfo.TimingPointAt(currentNote.StartTime); + + return controlPointInfo.GetClosestBeatDivisor(gapMs + currentTimingPoint.Time); + } + + private bool shouldProcessRhythm(int snap) + { + return snap switch + { + 3 => EnableOneThird.Value, + 6 => EnableOneSixth.Value, + 8 => EnableOneEighth.Value, + _ => false + }; + } + } +} diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index 70e429a344..0280992b9d 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -130,6 +130,7 @@ namespace osu.Game.Rulesets.Taiko new TaikoModEasy(), new TaikoModNoFail(), new MultiMod(new TaikoModHalfTime(), new TaikoModDaycore()), + new TaikoModSimplifiedRhythm(), }; case ModType.DifficultyIncrease: From 28b911f6ac0594ec0064d2850f713a61266aefae Mon Sep 17 00:00:00 2001 From: Hiviexd Date: Sun, 17 Nov 2024 17:53:11 +0100 Subject: [PATCH 02/15] format --- osu.Game.Rulesets.Taiko/Mods/TaikoModSimplifiedRhythm.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModSimplifiedRhythm.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModSimplifiedRhythm.cs index 14b819163b..17de560300 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModSimplifiedRhythm.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModSimplifiedRhythm.cs @@ -41,7 +41,7 @@ namespace osu.Game.Rulesets.Taiko.Mods // Snap conversions for rhythms var snapConversions = new Dictionary() { - { 8, 4 }, // 1/8 snap to 1/4 snap + { 8, 4 }, // 1/8 snap to 1/4 snap { 6, 4 }, // 1/6 snap to 1/4 snap { 3, 2 }, // 1/3 snap to 1/2 snap }; @@ -126,7 +126,7 @@ namespace osu.Game.Rulesets.Taiko.Mods 3 => EnableOneThird.Value, 6 => EnableOneSixth.Value, 8 => EnableOneEighth.Value, - _ => false + _ => false, }; } } From 617f8cce4a8e4ef86d925483541c2d4a32c798be Mon Sep 17 00:00:00 2001 From: Hiviexd Date: Sun, 17 Nov 2024 17:54:27 +0100 Subject: [PATCH 03/15] better names --- .../Mods/TaikoModSimplifiedRhythm.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModSimplifiedRhythm.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModSimplifiedRhythm.cs index 17de560300..b316260752 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModSimplifiedRhythm.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModSimplifiedRhythm.cs @@ -24,13 +24,13 @@ namespace osu.Game.Rulesets.Taiko.Mods public override ModType Type => ModType.DifficultyReduction; [SettingSource("One-third conversion", "Converts 1/3 snap to 1/2 snap.")] - public Bindable EnableOneThird { get; } = new BindableBool(false); + public Bindable OneThirdConversion { get; } = new BindableBool(false); [SettingSource("One-sixth conversion", "Converts 1/6 snap to 1/4 snap.")] - public Bindable EnableOneSixth { get; } = new BindableBool(true); + public Bindable OneSixthConversion { get; } = new BindableBool(true); [SettingSource("One-eighth conversion", "Converts 1/8 snap to 1/4 snap.")] - public Bindable EnableOneEighth { get; } = new BindableBool(false); + public Bindable OneEighthConversion { get; } = new BindableBool(false); public void ApplyToBeatmap(IBeatmap beatmap) { @@ -123,9 +123,9 @@ namespace osu.Game.Rulesets.Taiko.Mods { return snap switch { - 3 => EnableOneThird.Value, - 6 => EnableOneSixth.Value, - 8 => EnableOneEighth.Value, + 3 => OneThirdConversion.Value, + 6 => OneSixthConversion.Value, + 8 => OneEighthConversion.Value, _ => false, }; } From db081760498f616d80d2acbcea3cd945fa629dc1 Mon Sep 17 00:00:00 2001 From: Hiviexd Date: Sun, 17 Nov 2024 22:54:38 +0100 Subject: [PATCH 04/15] fix CI --- osu.Game.Rulesets.Taiko/Mods/TaikoModSimplifiedRhythm.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModSimplifiedRhythm.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModSimplifiedRhythm.cs index b316260752..c0a0c10b6b 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModSimplifiedRhythm.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModSimplifiedRhythm.cs @@ -36,17 +36,16 @@ namespace osu.Game.Rulesets.Taiko.Mods { var taikoBeatmap = (TaikoBeatmap)beatmap; var controlPointInfo = taikoBeatmap.ControlPointInfo; - List toRemove = []; + List toRemove = new List(); // Snap conversions for rhythms - var snapConversions = new Dictionary() + var snapConversions = new Dictionary { { 8, 4 }, // 1/8 snap to 1/4 snap { 6, 4 }, // 1/6 snap to 1/4 snap { 3, 2 }, // 1/3 snap to 1/2 snap }; - double beatLength = controlPointInfo.TimingPointAt(0).BeatLength; int patternStartIndex = 0; bool inPattern = false; @@ -63,6 +62,7 @@ namespace osu.Game.Rulesets.Taiko.Mods double snapValue = i < hits.Count - 1 ? getSnapBetweenNotes(controlPointInfo, hits[i], hits[i + 1]) : 1; // No next note, default to a safe 1/1 snap + if (snapValue == snapConversion.Key) { if (!inPattern) @@ -71,6 +71,7 @@ namespace osu.Game.Rulesets.Taiko.Mods } inPattern = true; } + // check if end of pattern or if we're on the last note if ((inPattern && snapValue != snapConversion.Key) || i == hits.Count) { @@ -95,7 +96,7 @@ namespace osu.Game.Rulesets.Taiko.Mods // 1/6 and 1/3: Adjust the second note and remove the third if (currentHitPosition % 3 == 1) { - hits[j].StartTime = hits[j - 1].StartTime + controlPointInfo.TimingPointAt(hits[j].StartTime).BeatLength / Convert.ToDouble(snapConversion.Value); + hits[j].StartTime = hits[j - 1].StartTime + (controlPointInfo.TimingPointAt(hits[j].StartTime).BeatLength / Convert.ToDouble(snapConversion.Value)); } else if (currentHitPosition % 3 == 2) { From 72210bf9fef29c50a4a9d7eea474b40a05c089c1 Mon Sep 17 00:00:00 2001 From: Hiviexd Date: Sun, 17 Nov 2024 23:34:30 +0100 Subject: [PATCH 05/15] blank line --- osu.Game.Rulesets.Taiko/Mods/TaikoModSimplifiedRhythm.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModSimplifiedRhythm.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModSimplifiedRhythm.cs index c0a0c10b6b..d54bb44d59 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModSimplifiedRhythm.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModSimplifiedRhythm.cs @@ -69,6 +69,7 @@ namespace osu.Game.Rulesets.Taiko.Mods { patternStartIndex = i; } + inPattern = true; } From 45ed2fdec297be5d8a0372d37878102097677a61 Mon Sep 17 00:00:00 2001 From: Hivie Date: Mon, 18 Nov 2024 12:00:28 +0100 Subject: [PATCH 06/15] apply review --- osu.Game.Rulesets.Taiko/Mods/TaikoModSimplifiedRhythm.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModSimplifiedRhythm.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModSimplifiedRhythm.cs index d54bb44d59..cb3cde309b 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModSimplifiedRhythm.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModSimplifiedRhythm.cs @@ -46,13 +46,14 @@ namespace osu.Game.Rulesets.Taiko.Mods { 3, 2 }, // 1/3 snap to 1/2 snap }; - int patternStartIndex = 0; bool inPattern = false; List hits = taikoBeatmap.HitObjects.Where(obj => obj is Hit).Cast().ToList(); foreach (var snapConversion in snapConversions) { + int patternStartIndex = 0; + // Skip processing if the corresponding conversion is disabled if (!shouldProcessRhythm(snapConversion.Key)) continue; @@ -73,8 +74,8 @@ namespace osu.Game.Rulesets.Taiko.Mods inPattern = true; } - // check if end of pattern or if we're on the last note - if ((inPattern && snapValue != snapConversion.Key) || i == hits.Count) + // check if end of pattern + if (inPattern && snapValue != snapConversion.Key) { // End of the pattern inPattern = false; @@ -109,7 +110,7 @@ namespace osu.Game.Rulesets.Taiko.Mods } // Remove queued notes - taikoBeatmap.HitObjects = taikoBeatmap.HitObjects.Except(toRemove).ToList(); + taikoBeatmap.HitObjects.RemoveAll(obj => toRemove.Contains(obj)); } } From 9bea112370e0ce9dc15911477f759df672327093 Mon Sep 17 00:00:00 2001 From: Hivie Date: Mon, 18 Nov 2024 12:09:13 +0100 Subject: [PATCH 07/15] better terminology --- osu.Game.Rulesets.Taiko/Mods/TaikoModSimplifiedRhythm.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModSimplifiedRhythm.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModSimplifiedRhythm.cs index cb3cde309b..57851173b8 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModSimplifiedRhythm.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModSimplifiedRhythm.cs @@ -23,13 +23,13 @@ namespace osu.Game.Rulesets.Taiko.Mods public override LocalisableString Description => "Simplify tricky rhythms!"; public override ModType Type => ModType.DifficultyReduction; - [SettingSource("One-third conversion", "Converts 1/3 snap to 1/2 snap.")] + [SettingSource("1/3 to 1/2 conversion", "Converts 1/3 patterns to 1/2 rhythm.")] public Bindable OneThirdConversion { get; } = new BindableBool(false); - [SettingSource("One-sixth conversion", "Converts 1/6 snap to 1/4 snap.")] + [SettingSource("1/6 to 1/4 conversion", "Converts 1/6 patterns to 1/4 rhythm.")] public Bindable OneSixthConversion { get; } = new BindableBool(true); - [SettingSource("One-eighth conversion", "Converts 1/8 snap to 1/4 snap.")] + [SettingSource("1/8 to 1/4 conversion", "Converts 1/8 patterns to 1/4 rhythm.")] public Bindable OneEighthConversion { get; } = new BindableBool(false); public void ApplyToBeatmap(IBeatmap beatmap) From a7b4f975ca7038e4ea33c73883921da90f9b60c7 Mon Sep 17 00:00:00 2001 From: Hivie Date: Mon, 18 Nov 2024 12:10:23 +0100 Subject: [PATCH 08/15] rename mod --- .../{TaikoModSimplifiedRhythm.cs => TaikoModSimplified.cs} | 6 +++--- osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) rename osu.Game.Rulesets.Taiko/Mods/{TaikoModSimplifiedRhythm.cs => TaikoModSimplified.cs} (96%) diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModSimplifiedRhythm.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModSimplified.cs similarity index 96% rename from osu.Game.Rulesets.Taiko/Mods/TaikoModSimplifiedRhythm.cs rename to osu.Game.Rulesets.Taiko/Mods/TaikoModSimplified.cs index 57851173b8..0dfa5a998a 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModSimplifiedRhythm.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModSimplified.cs @@ -15,10 +15,10 @@ using osu.Game.Rulesets.Taiko.Objects; namespace osu.Game.Rulesets.Taiko.Mods { - public class TaikoModSimplifiedRhythm : Mod, IApplicableToBeatmap + public class TaikoModSimplified : Mod, IApplicableToBeatmap { - public override string Name => "Simplified Rhythm"; - public override string Acronym => "SR"; + public override string Name => "Simplified"; + public override string Acronym => "SF"; public override double ScoreMultiplier => 0.6; public override LocalisableString Description => "Simplify tricky rhythms!"; public override ModType Type => ModType.DifficultyReduction; diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index 0280992b9d..f57d2a20f5 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -130,7 +130,7 @@ namespace osu.Game.Rulesets.Taiko new TaikoModEasy(), new TaikoModNoFail(), new MultiMod(new TaikoModHalfTime(), new TaikoModDaycore()), - new TaikoModSimplifiedRhythm(), + new TaikoModSimplified(), }; case ModType.DifficultyIncrease: From 3e8b26c483d426e64841f5ebe2199fe5796aa27c Mon Sep 17 00:00:00 2001 From: Hiviexd Date: Wed, 20 Nov 2024 01:49:01 +0100 Subject: [PATCH 09/15] simplify operation --- osu.Game.Rulesets.Taiko/Mods/TaikoModSimplified.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModSimplified.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModSimplified.cs index 0dfa5a998a..78eaf3199d 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModSimplified.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModSimplified.cs @@ -116,7 +116,7 @@ namespace osu.Game.Rulesets.Taiko.Mods private int getSnapBetweenNotes(ControlPointInfo controlPointInfo, Hit currentNote, Hit nextNote) { - double gapMs = Math.Max(currentNote.StartTime, nextNote.StartTime) - Math.Min(currentNote.StartTime, nextNote.StartTime); + double gapMs = nextNote.StartTime - currentNote.StartTime; var currentTimingPoint = controlPointInfo.TimingPointAt(currentNote.StartTime); return controlPointInfo.GetClosestBeatDivisor(gapMs + currentTimingPoint.Time); From 38e76d41b52207401e16aa9fd9fe275228b593ca Mon Sep 17 00:00:00 2001 From: Hiviexd Date: Wed, 20 Nov 2024 01:49:14 +0100 Subject: [PATCH 10/15] add unit tests --- .../Mods/TestSceneTaikoModSimplified.cs | 133 ++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 osu.Game.Rulesets.Taiko.Tests/Mods/TestSceneTaikoModSimplified.cs diff --git a/osu.Game.Rulesets.Taiko.Tests/Mods/TestSceneTaikoModSimplified.cs b/osu.Game.Rulesets.Taiko.Tests/Mods/TestSceneTaikoModSimplified.cs new file mode 100644 index 0000000000..4d8b2a4b4d --- /dev/null +++ b/osu.Game.Rulesets.Taiko.Tests/Mods/TestSceneTaikoModSimplified.cs @@ -0,0 +1,133 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using NUnit.Framework; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Replays; +using osu.Game.Rulesets.Taiko.Mods; +using osu.Game.Rulesets.Taiko.Objects; +using osu.Game.Rulesets.Taiko.Replays; + +namespace osu.Game.Rulesets.Taiko.Tests.Mods +{ + public partial class TestSceneTaikoModSimplified : TaikoModTestScene + { + [Test] + public void TestOneThirdConversion() + { + CreateModTest(new ModTestData + { + Mod = new TaikoModSimplified + { + OneThirdConversion = { Value = true }, + }, + Autoplay = false, + Beatmap = new Beatmap + { + HitObjects = new List + { + new Hit { StartTime = 1000, Type = HitType.Centre }, + new Hit { StartTime = 1500, Type = HitType.Centre }, + new Hit { StartTime = 2000, Type = HitType.Centre }, + new Hit { StartTime = 2333, Type = HitType.Centre }, + new Hit { StartTime = 2666, Type = HitType.Rim }, + new Hit { StartTime = 3000, Type = HitType.Centre }, + new Hit { StartTime = 3500, Type = HitType.Centre }, + }, + }, + ReplayFrames = new List + { + new TaikoReplayFrame(1000, TaikoAction.LeftCentre), + new TaikoReplayFrame(1200), + new TaikoReplayFrame(1500, TaikoAction.LeftCentre), + new TaikoReplayFrame(1700), + new TaikoReplayFrame(2000, TaikoAction.LeftCentre), + new TaikoReplayFrame(2200), + new TaikoReplayFrame(2500, TaikoAction.LeftCentre), + new TaikoReplayFrame(2700), + new TaikoReplayFrame(3000, TaikoAction.LeftCentre), + new TaikoReplayFrame(3200), + new TaikoReplayFrame(3500, TaikoAction.LeftCentre), + new TaikoReplayFrame(3700), + }, + PassCondition = () => Player.ScoreProcessor.Combo.Value == 6 + }); + } + + [Test] + public void TestOneSixthConversion() => CreateModTest(new ModTestData + { + Mod = new TaikoModSimplified + { + OneSixthConversion = { Value = true } + }, + Autoplay = false, + Beatmap = new Beatmap + { + HitObjects = new List + { + new Hit { StartTime = 1000, Type = HitType.Centre }, + new Hit { StartTime = 1250, Type = HitType.Centre }, + new Hit { StartTime = 1500, Type = HitType.Centre }, + new Hit { StartTime = 1666, Type = HitType.Centre }, + new Hit { StartTime = 1833, Type = HitType.Rim }, + new Hit { StartTime = 2000, Type = HitType.Centre }, + new Hit { StartTime = 2250, Type = HitType.Centre }, + }, + }, + ReplayFrames = new List + { + new TaikoReplayFrame(1000, TaikoAction.LeftCentre), + new TaikoReplayFrame(1200), + new TaikoReplayFrame(1250, TaikoAction.LeftCentre), + new TaikoReplayFrame(1450), + new TaikoReplayFrame(1500, TaikoAction.LeftCentre), + new TaikoReplayFrame(1600), + new TaikoReplayFrame(1750, TaikoAction.LeftCentre), + new TaikoReplayFrame(1800), + new TaikoReplayFrame(2000, TaikoAction.LeftCentre), + new TaikoReplayFrame(2200), + new TaikoReplayFrame(2250, TaikoAction.LeftCentre), + new TaikoReplayFrame(2450), + }, + PassCondition = () => Player.ScoreProcessor.Combo.Value == 6 + }); + + [Test] + public void TestOneEighthConversion() => CreateModTest(new ModTestData + { + Mod = new TaikoModSimplified + { + OneEighthConversion = { Value = true } + }, + Autoplay = false, + Beatmap = new Beatmap + { + HitObjects = new List + { + new Hit { StartTime = 1000, Type = HitType.Centre }, + new Hit { StartTime = 1250, Type = HitType.Centre }, + new Hit { StartTime = 1500, Type = HitType.Centre }, + new Hit { StartTime = 1625, Type = HitType.Rim }, + new Hit { StartTime = 1750, Type = HitType.Centre }, + new Hit { StartTime = 2000, Type = HitType.Centre }, + }, + }, + ReplayFrames = new List + { + new TaikoReplayFrame(1000, TaikoAction.LeftCentre), + new TaikoReplayFrame(1200), + new TaikoReplayFrame(1250, TaikoAction.LeftCentre), + new TaikoReplayFrame(1450), + new TaikoReplayFrame(1500, TaikoAction.LeftCentre), + new TaikoReplayFrame(1700), + new TaikoReplayFrame(1750, TaikoAction.LeftCentre), + new TaikoReplayFrame(1900), + new TaikoReplayFrame(2000, TaikoAction.LeftCentre), + }, + PassCondition = () => Player.ScoreProcessor.Combo.Value == 5 + }); + } +} From d4f29487d3aad90cdc1ae44643a109206d2ddd35 Mon Sep 17 00:00:00 2001 From: Hiviexd Date: Fri, 22 Nov 2024 10:26:49 +0100 Subject: [PATCH 11/15] fix tests --- .../Mods/TestSceneTaikoModSimplified.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/osu.Game.Rulesets.Taiko.Tests/Mods/TestSceneTaikoModSimplified.cs b/osu.Game.Rulesets.Taiko.Tests/Mods/TestSceneTaikoModSimplified.cs index 4d8b2a4b4d..825c8cb1ad 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Mods/TestSceneTaikoModSimplified.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Mods/TestSceneTaikoModSimplified.cs @@ -24,15 +24,15 @@ namespace osu.Game.Rulesets.Taiko.Tests.Mods OneThirdConversion = { Value = true }, }, Autoplay = false, - Beatmap = new Beatmap + CreateBeatmap = () => new Beatmap { HitObjects = new List { new Hit { StartTime = 1000, Type = HitType.Centre }, new Hit { StartTime = 1500, Type = HitType.Centre }, new Hit { StartTime = 2000, Type = HitType.Centre }, - new Hit { StartTime = 2333, Type = HitType.Centre }, - new Hit { StartTime = 2666, Type = HitType.Rim }, + new Hit { StartTime = 2333, Type = HitType.Centre }, // mod moves this to 2500 + new Hit { StartTime = 2666, Type = HitType.Rim }, // mod removes this new Hit { StartTime = 3000, Type = HitType.Centre }, new Hit { StartTime = 3500, Type = HitType.Centre }, }, @@ -64,15 +64,15 @@ namespace osu.Game.Rulesets.Taiko.Tests.Mods OneSixthConversion = { Value = true } }, Autoplay = false, - Beatmap = new Beatmap + CreateBeatmap = () => new Beatmap { HitObjects = new List { new Hit { StartTime = 1000, Type = HitType.Centre }, new Hit { StartTime = 1250, Type = HitType.Centre }, new Hit { StartTime = 1500, Type = HitType.Centre }, - new Hit { StartTime = 1666, Type = HitType.Centre }, - new Hit { StartTime = 1833, Type = HitType.Rim }, + new Hit { StartTime = 1666, Type = HitType.Centre }, // mod moves this to 1750 + new Hit { StartTime = 1833, Type = HitType.Rim }, // mod removes this new Hit { StartTime = 2000, Type = HitType.Centre }, new Hit { StartTime = 2250, Type = HitType.Centre }, }, @@ -103,14 +103,14 @@ namespace osu.Game.Rulesets.Taiko.Tests.Mods OneEighthConversion = { Value = true } }, Autoplay = false, - Beatmap = new Beatmap + CreateBeatmap = () => new Beatmap { HitObjects = new List { new Hit { StartTime = 1000, Type = HitType.Centre }, new Hit { StartTime = 1250, Type = HitType.Centre }, new Hit { StartTime = 1500, Type = HitType.Centre }, - new Hit { StartTime = 1625, Type = HitType.Rim }, + new Hit { StartTime = 1625, Type = HitType.Rim }, // mod removes this new Hit { StartTime = 1750, Type = HitType.Centre }, new Hit { StartTime = 2000, Type = HitType.Centre }, }, From 93e7afd5f35bae93108b2318077ac56a92d27fea Mon Sep 17 00:00:00 2001 From: Hiviexd Date: Fri, 22 Nov 2024 11:21:48 +0100 Subject: [PATCH 12/15] improve conversion process to reduce breakage in rare cases --- .../Mods/TestSceneTaikoModSimplified.cs | 10 +++++----- osu.Game.Rulesets.Taiko/Mods/TaikoModSimplified.cs | 11 ++++++----- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Taiko.Tests/Mods/TestSceneTaikoModSimplified.cs b/osu.Game.Rulesets.Taiko.Tests/Mods/TestSceneTaikoModSimplified.cs index 825c8cb1ad..8ce6698857 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Mods/TestSceneTaikoModSimplified.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Mods/TestSceneTaikoModSimplified.cs @@ -31,8 +31,8 @@ namespace osu.Game.Rulesets.Taiko.Tests.Mods new Hit { StartTime = 1000, Type = HitType.Centre }, new Hit { StartTime = 1500, Type = HitType.Centre }, new Hit { StartTime = 2000, Type = HitType.Centre }, - new Hit { StartTime = 2333, Type = HitType.Centre }, // mod moves this to 2500 - new Hit { StartTime = 2666, Type = HitType.Rim }, // mod removes this + new Hit { StartTime = 2333, Type = HitType.Rim }, // mod removes this + new Hit { StartTime = 2666, Type = HitType.Centre }, // mod moves this to 2500 new Hit { StartTime = 3000, Type = HitType.Centre }, new Hit { StartTime = 3500, Type = HitType.Centre }, }, @@ -71,8 +71,8 @@ namespace osu.Game.Rulesets.Taiko.Tests.Mods new Hit { StartTime = 1000, Type = HitType.Centre }, new Hit { StartTime = 1250, Type = HitType.Centre }, new Hit { StartTime = 1500, Type = HitType.Centre }, - new Hit { StartTime = 1666, Type = HitType.Centre }, // mod moves this to 1750 - new Hit { StartTime = 1833, Type = HitType.Rim }, // mod removes this + new Hit { StartTime = 1666, Type = HitType.Rim }, // mod removes this + new Hit { StartTime = 1833, Type = HitType.Centre }, // mod moves this to 1750 new Hit { StartTime = 2000, Type = HitType.Centre }, new Hit { StartTime = 2250, Type = HitType.Centre }, }, @@ -110,7 +110,7 @@ namespace osu.Game.Rulesets.Taiko.Tests.Mods new Hit { StartTime = 1000, Type = HitType.Centre }, new Hit { StartTime = 1250, Type = HitType.Centre }, new Hit { StartTime = 1500, Type = HitType.Centre }, - new Hit { StartTime = 1625, Type = HitType.Rim }, // mod removes this + new Hit { StartTime = 1625, Type = HitType.Rim }, // mod removes this new Hit { StartTime = 1750, Type = HitType.Centre }, new Hit { StartTime = 2000, Type = HitType.Centre }, }, diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModSimplified.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModSimplified.cs index 78eaf3199d..70e76ed8f3 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModSimplified.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModSimplified.cs @@ -95,15 +95,16 @@ namespace osu.Game.Rulesets.Taiko.Mods } else { - // 1/6 and 1/3: Adjust the second note and remove the third + // 1/6 and 1/3: Remove the second note and adjust the third if (currentHitPosition % 3 == 1) - { - hits[j].StartTime = hits[j - 1].StartTime + (controlPointInfo.TimingPointAt(hits[j].StartTime).BeatLength / Convert.ToDouble(snapConversion.Value)); - } - else if (currentHitPosition % 3 == 2) { toRemove.Add(hits[j]); } + else if (currentHitPosition % 3 == 2 && j < hits.Count - 1) + { + double offset = controlPointInfo.TimingPointAt(hits[j].StartTime).BeatLength / Convert.ToDouble(snapConversion.Value); + hits[j].StartTime = hits[j + 1].StartTime - offset; + } } } } From ea4cbb5c36f31804077a0f39cc52691dc7edea41 Mon Sep 17 00:00:00 2001 From: Hiviexd Date: Fri, 22 Nov 2024 11:33:33 +0100 Subject: [PATCH 13/15] rename mod to `Quarterize` --- ...ikoModSimplified.cs => TestSceneTaikoModQuarterize.cs} | 8 ++++---- .../Mods/{TaikoModSimplified.cs => TaikoModQuarterize.cs} | 6 +++--- osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) rename osu.Game.Rulesets.Taiko.Tests/Mods/{TestSceneTaikoModSimplified.cs => TestSceneTaikoModQuarterize.cs} (96%) rename osu.Game.Rulesets.Taiko/Mods/{TaikoModSimplified.cs => TaikoModQuarterize.cs} (96%) diff --git a/osu.Game.Rulesets.Taiko.Tests/Mods/TestSceneTaikoModSimplified.cs b/osu.Game.Rulesets.Taiko.Tests/Mods/TestSceneTaikoModQuarterize.cs similarity index 96% rename from osu.Game.Rulesets.Taiko.Tests/Mods/TestSceneTaikoModSimplified.cs rename to osu.Game.Rulesets.Taiko.Tests/Mods/TestSceneTaikoModQuarterize.cs index 8ce6698857..3e5e620073 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Mods/TestSceneTaikoModSimplified.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Mods/TestSceneTaikoModQuarterize.cs @@ -12,14 +12,14 @@ using osu.Game.Rulesets.Taiko.Replays; namespace osu.Game.Rulesets.Taiko.Tests.Mods { - public partial class TestSceneTaikoModSimplified : TaikoModTestScene + public partial class TestSceneTaikoModQuarterize : TaikoModTestScene { [Test] public void TestOneThirdConversion() { CreateModTest(new ModTestData { - Mod = new TaikoModSimplified + Mod = new TaikoModQuarterize { OneThirdConversion = { Value = true }, }, @@ -59,7 +59,7 @@ namespace osu.Game.Rulesets.Taiko.Tests.Mods [Test] public void TestOneSixthConversion() => CreateModTest(new ModTestData { - Mod = new TaikoModSimplified + Mod = new TaikoModQuarterize { OneSixthConversion = { Value = true } }, @@ -98,7 +98,7 @@ namespace osu.Game.Rulesets.Taiko.Tests.Mods [Test] public void TestOneEighthConversion() => CreateModTest(new ModTestData { - Mod = new TaikoModSimplified + Mod = new TaikoModQuarterize { OneEighthConversion = { Value = true } }, diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModSimplified.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModQuarterize.cs similarity index 96% rename from osu.Game.Rulesets.Taiko/Mods/TaikoModSimplified.cs rename to osu.Game.Rulesets.Taiko/Mods/TaikoModQuarterize.cs index 70e76ed8f3..c486c6d8b2 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModSimplified.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModQuarterize.cs @@ -15,10 +15,10 @@ using osu.Game.Rulesets.Taiko.Objects; namespace osu.Game.Rulesets.Taiko.Mods { - public class TaikoModSimplified : Mod, IApplicableToBeatmap + public class TaikoModQuarterize : Mod, IApplicableToBeatmap { - public override string Name => "Simplified"; - public override string Acronym => "SF"; + public override string Name => "Quarterize"; + public override string Acronym => "QR"; public override double ScoreMultiplier => 0.6; public override LocalisableString Description => "Simplify tricky rhythms!"; public override ModType Type => ModType.DifficultyReduction; diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index f57d2a20f5..cce7f61d2f 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -130,7 +130,7 @@ namespace osu.Game.Rulesets.Taiko new TaikoModEasy(), new TaikoModNoFail(), new MultiMod(new TaikoModHalfTime(), new TaikoModDaycore()), - new TaikoModSimplified(), + new TaikoModQuarterize(), }; case ModType.DifficultyIncrease: From ad21b7f3412ac791b8035b58ff0872762cfb1f5f Mon Sep 17 00:00:00 2001 From: Hivie Date: Fri, 22 Nov 2024 13:48:15 +0100 Subject: [PATCH 14/15] cleaner expression --- osu.Game.Rulesets.Taiko/Mods/TaikoModQuarterize.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModQuarterize.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModQuarterize.cs index c486c6d8b2..e2ab4853fa 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModQuarterize.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModQuarterize.cs @@ -39,11 +39,11 @@ namespace osu.Game.Rulesets.Taiko.Mods List toRemove = new List(); // Snap conversions for rhythms - var snapConversions = new Dictionary + var snapConversions = new Dictionary { - { 8, 4 }, // 1/8 snap to 1/4 snap - { 6, 4 }, // 1/6 snap to 1/4 snap - { 3, 2 }, // 1/3 snap to 1/2 snap + { 8, 4.0 }, // 1/8 snap to 1/4 snap + { 6, 4.0 }, // 1/6 snap to 1/4 snap + { 3, 2.0 }, // 1/3 snap to 1/2 snap }; bool inPattern = false; @@ -102,7 +102,7 @@ namespace osu.Game.Rulesets.Taiko.Mods } else if (currentHitPosition % 3 == 2 && j < hits.Count - 1) { - double offset = controlPointInfo.TimingPointAt(hits[j].StartTime).BeatLength / Convert.ToDouble(snapConversion.Value); + double offset = controlPointInfo.TimingPointAt(hits[j].StartTime).BeatLength / snapConversion.Value; hits[j].StartTime = hits[j + 1].StartTime - offset; } } From 25bb6cbf9b3e4f33e32225f764dd686e296c7123 Mon Sep 17 00:00:00 2001 From: Hivie Date: Fri, 22 Nov 2024 14:18:09 +0100 Subject: [PATCH 15/15] remove unused import --- osu.Game.Rulesets.Taiko/Mods/TaikoModQuarterize.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModQuarterize.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModQuarterize.cs index e2ab4853fa..af319b1d41 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModQuarterize.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModQuarterize.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Bindables;