1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-05 09:42:54 +08:00

implement proposed osu!mania mod, Full Perfect

This commit is contained in:
Milo 2024-11-11 18:52:30 -04:00
parent bca42e9d24
commit 5977fbfce7
2 changed files with 489 additions and 449 deletions

View File

@ -1,449 +1,449 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Sprites;
using osu.Framework.Input.Bindings; using osu.Framework.Input.Bindings;
using osu.Framework.Localisation; using osu.Framework.Localisation;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Beatmaps.Legacy; using osu.Game.Beatmaps.Legacy;
using osu.Game.Configuration; using osu.Game.Configuration;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Overlays.Settings; using osu.Game.Overlays.Settings;
using osu.Game.Rulesets.Configuration; using osu.Game.Rulesets.Configuration;
using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Difficulty;
using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Filter; using osu.Game.Rulesets.Filter;
using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Beatmaps;
using osu.Game.Rulesets.Mania.Configuration; using osu.Game.Rulesets.Mania.Configuration;
using osu.Game.Rulesets.Mania.Difficulty; using osu.Game.Rulesets.Mania.Difficulty;
using osu.Game.Rulesets.Mania.Edit; using osu.Game.Rulesets.Mania.Edit;
using osu.Game.Rulesets.Mania.Edit.Setup; using osu.Game.Rulesets.Mania.Edit.Setup;
using osu.Game.Rulesets.Mania.Mods; using osu.Game.Rulesets.Mania.Mods;
using osu.Game.Rulesets.Mania.Replays; using osu.Game.Rulesets.Mania.Replays;
using osu.Game.Rulesets.Mania.Scoring; using osu.Game.Rulesets.Mania.Scoring;
using osu.Game.Rulesets.Mania.Skinning.Argon; using osu.Game.Rulesets.Mania.Skinning.Argon;
using osu.Game.Rulesets.Mania.Skinning.Default; using osu.Game.Rulesets.Mania.Skinning.Default;
using osu.Game.Rulesets.Mania.Skinning.Legacy; using osu.Game.Rulesets.Mania.Skinning.Legacy;
using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Mania.UI;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Replays.Types; using osu.Game.Rulesets.Replays.Types;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.Scoring.Legacy; using osu.Game.Rulesets.Scoring.Legacy;
using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI;
using osu.Game.Scoring; using osu.Game.Scoring;
using osu.Game.Screens.Edit.Setup; using osu.Game.Screens.Edit.Setup;
using osu.Game.Screens.Ranking.Statistics; using osu.Game.Screens.Ranking.Statistics;
using osu.Game.Skinning; using osu.Game.Skinning;
namespace osu.Game.Rulesets.Mania namespace osu.Game.Rulesets.Mania
{ {
public class ManiaRuleset : Ruleset, ILegacyRuleset public class ManiaRuleset : Ruleset, ILegacyRuleset
{ {
/// <summary> /// <summary>
/// The maximum number of supported keys in a single stage. /// The maximum number of supported keys in a single stage.
/// </summary> /// </summary>
public const int MAX_STAGE_KEYS = 10; public const int MAX_STAGE_KEYS = 10;
public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList<Mod>? mods = null) => new DrawableManiaRuleset(this, beatmap, mods); public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList<Mod>? mods = null) => new DrawableManiaRuleset(this, beatmap, mods);
public override ScoreProcessor CreateScoreProcessor() => new ManiaScoreProcessor(); public override ScoreProcessor CreateScoreProcessor() => new ManiaScoreProcessor();
public override HealthProcessor CreateHealthProcessor(double drainStartTime) => new ManiaHealthProcessor(drainStartTime); public override HealthProcessor CreateHealthProcessor(double drainStartTime) => new ManiaHealthProcessor(drainStartTime);
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new ManiaBeatmapConverter(beatmap, this); public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new ManiaBeatmapConverter(beatmap, this);
public override PerformanceCalculator CreatePerformanceCalculator() => new ManiaPerformanceCalculator(); public override PerformanceCalculator CreatePerformanceCalculator() => new ManiaPerformanceCalculator();
public const string SHORT_NAME = "mania"; public const string SHORT_NAME = "mania";
public override string RulesetAPIVersionSupported => CURRENT_RULESET_API_VERSION; public override string RulesetAPIVersionSupported => CURRENT_RULESET_API_VERSION;
public override HitObjectComposer CreateHitObjectComposer() => new ManiaHitObjectComposer(this); public override HitObjectComposer CreateHitObjectComposer() => new ManiaHitObjectComposer(this);
public override IBeatmapVerifier CreateBeatmapVerifier() => new ManiaBeatmapVerifier(); public override IBeatmapVerifier CreateBeatmapVerifier() => new ManiaBeatmapVerifier();
public override ISkin? CreateSkinTransformer(ISkin skin, IBeatmap beatmap) public override ISkin? CreateSkinTransformer(ISkin skin, IBeatmap beatmap)
{ {
switch (skin) switch (skin)
{ {
case TrianglesSkin: case TrianglesSkin:
return new ManiaTrianglesSkinTransformer(skin, beatmap); return new ManiaTrianglesSkinTransformer(skin, beatmap);
case ArgonSkin: case ArgonSkin:
return new ManiaArgonSkinTransformer(skin, beatmap); return new ManiaArgonSkinTransformer(skin, beatmap);
case DefaultLegacySkin: case DefaultLegacySkin:
return new ManiaClassicSkinTransformer(skin, beatmap); return new ManiaClassicSkinTransformer(skin, beatmap);
case LegacySkin: case LegacySkin:
return new ManiaLegacySkinTransformer(skin, beatmap); return new ManiaLegacySkinTransformer(skin, beatmap);
} }
return null; return null;
} }
public override IEnumerable<Mod> ConvertFromLegacyMods(LegacyMods mods) public override IEnumerable<Mod> ConvertFromLegacyMods(LegacyMods mods)
{ {
if (mods.HasFlag(LegacyMods.Nightcore)) if (mods.HasFlag(LegacyMods.Nightcore))
yield return new ManiaModNightcore(); yield return new ManiaModNightcore();
else if (mods.HasFlag(LegacyMods.DoubleTime)) else if (mods.HasFlag(LegacyMods.DoubleTime))
yield return new ManiaModDoubleTime(); yield return new ManiaModDoubleTime();
if (mods.HasFlag(LegacyMods.Perfect)) if (mods.HasFlag(LegacyMods.Perfect))
yield return new ManiaModPerfect(); yield return new ManiaModPerfect();
else if (mods.HasFlag(LegacyMods.SuddenDeath)) else if (mods.HasFlag(LegacyMods.SuddenDeath))
yield return new ManiaModSuddenDeath(); yield return new ManiaModSuddenDeath();
if (mods.HasFlag(LegacyMods.Cinema)) if (mods.HasFlag(LegacyMods.Cinema))
yield return new ManiaModCinema(); yield return new ManiaModCinema();
else if (mods.HasFlag(LegacyMods.Autoplay)) else if (mods.HasFlag(LegacyMods.Autoplay))
yield return new ManiaModAutoplay(); yield return new ManiaModAutoplay();
if (mods.HasFlag(LegacyMods.Easy)) if (mods.HasFlag(LegacyMods.Easy))
yield return new ManiaModEasy(); yield return new ManiaModEasy();
if (mods.HasFlag(LegacyMods.FadeIn)) if (mods.HasFlag(LegacyMods.FadeIn))
yield return new ManiaModFadeIn(); yield return new ManiaModFadeIn();
if (mods.HasFlag(LegacyMods.Flashlight)) if (mods.HasFlag(LegacyMods.Flashlight))
yield return new ManiaModFlashlight(); yield return new ManiaModFlashlight();
if (mods.HasFlag(LegacyMods.HalfTime)) if (mods.HasFlag(LegacyMods.HalfTime))
yield return new ManiaModHalfTime(); yield return new ManiaModHalfTime();
if (mods.HasFlag(LegacyMods.HardRock)) if (mods.HasFlag(LegacyMods.HardRock))
yield return new ManiaModHardRock(); yield return new ManiaModHardRock();
if (mods.HasFlag(LegacyMods.Hidden)) if (mods.HasFlag(LegacyMods.Hidden))
yield return new ManiaModHidden(); yield return new ManiaModHidden();
if (mods.HasFlag(LegacyMods.Key1)) if (mods.HasFlag(LegacyMods.Key1))
yield return new ManiaModKey1(); yield return new ManiaModKey1();
if (mods.HasFlag(LegacyMods.Key2)) if (mods.HasFlag(LegacyMods.Key2))
yield return new ManiaModKey2(); yield return new ManiaModKey2();
if (mods.HasFlag(LegacyMods.Key3)) if (mods.HasFlag(LegacyMods.Key3))
yield return new ManiaModKey3(); yield return new ManiaModKey3();
if (mods.HasFlag(LegacyMods.Key4)) if (mods.HasFlag(LegacyMods.Key4))
yield return new ManiaModKey4(); yield return new ManiaModKey4();
if (mods.HasFlag(LegacyMods.Key5)) if (mods.HasFlag(LegacyMods.Key5))
yield return new ManiaModKey5(); yield return new ManiaModKey5();
if (mods.HasFlag(LegacyMods.Key6)) if (mods.HasFlag(LegacyMods.Key6))
yield return new ManiaModKey6(); yield return new ManiaModKey6();
if (mods.HasFlag(LegacyMods.Key7)) if (mods.HasFlag(LegacyMods.Key7))
yield return new ManiaModKey7(); yield return new ManiaModKey7();
if (mods.HasFlag(LegacyMods.Key8)) if (mods.HasFlag(LegacyMods.Key8))
yield return new ManiaModKey8(); yield return new ManiaModKey8();
if (mods.HasFlag(LegacyMods.Key9)) if (mods.HasFlag(LegacyMods.Key9))
yield return new ManiaModKey9(); yield return new ManiaModKey9();
if (mods.HasFlag(LegacyMods.KeyCoop)) if (mods.HasFlag(LegacyMods.KeyCoop))
yield return new ManiaModDualStages(); yield return new ManiaModDualStages();
if (mods.HasFlag(LegacyMods.NoFail)) if (mods.HasFlag(LegacyMods.NoFail))
yield return new ManiaModNoFail(); yield return new ManiaModNoFail();
if (mods.HasFlag(LegacyMods.Random)) if (mods.HasFlag(LegacyMods.Random))
yield return new ManiaModRandom(); yield return new ManiaModRandom();
if (mods.HasFlag(LegacyMods.Mirror)) if (mods.HasFlag(LegacyMods.Mirror))
yield return new ManiaModMirror(); yield return new ManiaModMirror();
if (mods.HasFlag(LegacyMods.ScoreV2)) if (mods.HasFlag(LegacyMods.ScoreV2))
yield return new ModScoreV2(); yield return new ModScoreV2();
} }
public override LegacyMods ConvertToLegacyMods(Mod[] mods) public override LegacyMods ConvertToLegacyMods(Mod[] mods)
{ {
var value = base.ConvertToLegacyMods(mods); var value = base.ConvertToLegacyMods(mods);
foreach (var mod in mods) foreach (var mod in mods)
{ {
switch (mod) switch (mod)
{ {
case ManiaModKey1: case ManiaModKey1:
value |= LegacyMods.Key1; value |= LegacyMods.Key1;
break; break;
case ManiaModKey2: case ManiaModKey2:
value |= LegacyMods.Key2; value |= LegacyMods.Key2;
break; break;
case ManiaModKey3: case ManiaModKey3:
value |= LegacyMods.Key3; value |= LegacyMods.Key3;
break; break;
case ManiaModKey4: case ManiaModKey4:
value |= LegacyMods.Key4; value |= LegacyMods.Key4;
break; break;
case ManiaModKey5: case ManiaModKey5:
value |= LegacyMods.Key5; value |= LegacyMods.Key5;
break; break;
case ManiaModKey6: case ManiaModKey6:
value |= LegacyMods.Key6; value |= LegacyMods.Key6;
break; break;
case ManiaModKey7: case ManiaModKey7:
value |= LegacyMods.Key7; value |= LegacyMods.Key7;
break; break;
case ManiaModKey8: case ManiaModKey8:
value |= LegacyMods.Key8; value |= LegacyMods.Key8;
break; break;
case ManiaModKey9: case ManiaModKey9:
value |= LegacyMods.Key9; value |= LegacyMods.Key9;
break; break;
case ManiaModDualStages: case ManiaModDualStages:
value |= LegacyMods.KeyCoop; value |= LegacyMods.KeyCoop;
break; break;
case ManiaModFadeIn: case ManiaModFadeIn:
value |= LegacyMods.FadeIn; value |= LegacyMods.FadeIn;
value &= ~LegacyMods.Hidden; // this is toggled on in the base call due to inheritance, but we don't want that. value &= ~LegacyMods.Hidden; // this is toggled on in the base call due to inheritance, but we don't want that.
break; break;
case ManiaModMirror: case ManiaModMirror:
value |= LegacyMods.Mirror; value |= LegacyMods.Mirror;
break; break;
case ManiaModRandom: case ManiaModRandom:
value |= LegacyMods.Random; value |= LegacyMods.Random;
break; break;
} }
} }
return value; return value;
} }
public override IEnumerable<Mod> GetModsFor(ModType type) public override IEnumerable<Mod> GetModsFor(ModType type)
{ {
switch (type) switch (type)
{ {
case ModType.DifficultyReduction: case ModType.DifficultyReduction:
return new Mod[] return new Mod[]
{ {
new ManiaModEasy(), new ManiaModEasy(),
new ManiaModNoFail(), new ManiaModNoFail(),
new MultiMod(new ManiaModHalfTime(), new ManiaModDaycore()), new MultiMod(new ManiaModHalfTime(), new ManiaModDaycore()),
new ManiaModNoRelease(), new ManiaModNoRelease(),
}; };
case ModType.DifficultyIncrease: case ModType.DifficultyIncrease:
return new Mod[] return new Mod[]
{ {
new ManiaModHardRock(), new ManiaModHardRock(),
new MultiMod(new ManiaModSuddenDeath(), new ManiaModPerfect()), new MultiMod(new ManiaModSuddenDeath(), new ManiaModPerfect(), new ManiaModFullPerfect()),
new MultiMod(new ManiaModDoubleTime(), new ManiaModNightcore()), new MultiMod(new ManiaModDoubleTime(), new ManiaModNightcore()),
new MultiMod(new ManiaModFadeIn(), new ManiaModHidden(), new ManiaModCover()), new MultiMod(new ManiaModFadeIn(), new ManiaModHidden(), new ManiaModCover()),
new ManiaModFlashlight(), new ManiaModFlashlight(),
new ModAccuracyChallenge(), new ModAccuracyChallenge(),
}; };
case ModType.Conversion: case ModType.Conversion:
return new Mod[] return new Mod[]
{ {
new ManiaModRandom(), new ManiaModRandom(),
new ManiaModDualStages(), new ManiaModDualStages(),
new ManiaModMirror(), new ManiaModMirror(),
new ManiaModDifficultyAdjust(), new ManiaModDifficultyAdjust(),
new ManiaModClassic(), new ManiaModClassic(),
new ManiaModInvert(), new ManiaModInvert(),
new ManiaModConstantSpeed(), new ManiaModConstantSpeed(),
new ManiaModHoldOff(), new ManiaModHoldOff(),
new MultiMod( new MultiMod(
new ManiaModKey1(), new ManiaModKey1(),
new ManiaModKey2(), new ManiaModKey2(),
new ManiaModKey3(), new ManiaModKey3(),
new ManiaModKey4(), new ManiaModKey4(),
new ManiaModKey5(), new ManiaModKey5(),
new ManiaModKey6(), new ManiaModKey6(),
new ManiaModKey7(), new ManiaModKey7(),
new ManiaModKey8(), new ManiaModKey8(),
new ManiaModKey9(), new ManiaModKey9(),
new ManiaModKey10() new ManiaModKey10()
), ),
}; };
case ModType.Automation: case ModType.Automation:
return new Mod[] return new Mod[]
{ {
new MultiMod(new ManiaModAutoplay(), new ManiaModCinema()), new MultiMod(new ManiaModAutoplay(), new ManiaModCinema()),
}; };
case ModType.Fun: case ModType.Fun:
return new Mod[] return new Mod[]
{ {
new MultiMod(new ModWindUp(), new ModWindDown()), new MultiMod(new ModWindUp(), new ModWindDown()),
new ManiaModMuted(), new ManiaModMuted(),
new ModAdaptiveSpeed() new ModAdaptiveSpeed()
}; };
case ModType.System: case ModType.System:
return new Mod[] return new Mod[]
{ {
new ModScoreV2(), new ModScoreV2(),
}; };
default: default:
return Array.Empty<Mod>(); return Array.Empty<Mod>();
} }
} }
public override string Description => "osu!mania"; public override string Description => "osu!mania";
public override string ShortName => SHORT_NAME; public override string ShortName => SHORT_NAME;
public override string PlayingVerb => "Smashing keys"; public override string PlayingVerb => "Smashing keys";
public override Drawable CreateIcon() => new SpriteIcon { Icon = OsuIcon.RulesetMania }; public override Drawable CreateIcon() => new SpriteIcon { Icon = OsuIcon.RulesetMania };
public override DifficultyCalculator CreateDifficultyCalculator(IWorkingBeatmap beatmap) => new ManiaDifficultyCalculator(RulesetInfo, beatmap); public override DifficultyCalculator CreateDifficultyCalculator(IWorkingBeatmap beatmap) => new ManiaDifficultyCalculator(RulesetInfo, beatmap);
public int LegacyID => 3; public int LegacyID => 3;
public ILegacyScoreSimulator CreateLegacyScoreSimulator() => new ManiaLegacyScoreSimulator(); public ILegacyScoreSimulator CreateLegacyScoreSimulator() => new ManiaLegacyScoreSimulator();
public override IConvertibleReplayFrame CreateConvertibleReplayFrame() => new ManiaReplayFrame(); public override IConvertibleReplayFrame CreateConvertibleReplayFrame() => new ManiaReplayFrame();
public override IRulesetConfigManager CreateConfig(SettingsStore? settings) => new ManiaRulesetConfigManager(settings, RulesetInfo); public override IRulesetConfigManager CreateConfig(SettingsStore? settings) => new ManiaRulesetConfigManager(settings, RulesetInfo);
public override RulesetSettingsSubsection CreateSettings() => new ManiaSettingsSubsection(this); public override RulesetSettingsSubsection CreateSettings() => new ManiaSettingsSubsection(this);
public override IEnumerable<int> AvailableVariants public override IEnumerable<int> AvailableVariants
{ {
get get
{ {
for (int i = 1; i <= MAX_STAGE_KEYS; i++) for (int i = 1; i <= MAX_STAGE_KEYS; i++)
yield return (int)PlayfieldType.Single + i; yield return (int)PlayfieldType.Single + i;
for (int i = 2; i <= MAX_STAGE_KEYS * 2; i += 2) for (int i = 2; i <= MAX_STAGE_KEYS * 2; i += 2)
yield return (int)PlayfieldType.Dual + i; yield return (int)PlayfieldType.Dual + i;
} }
} }
public override IEnumerable<KeyBinding> GetDefaultKeyBindings(int variant = 0) public override IEnumerable<KeyBinding> GetDefaultKeyBindings(int variant = 0)
{ {
switch (getPlayfieldType(variant)) switch (getPlayfieldType(variant))
{ {
case PlayfieldType.Single: case PlayfieldType.Single:
return new SingleStageVariantGenerator(variant).GenerateMappings(); return new SingleStageVariantGenerator(variant).GenerateMappings();
case PlayfieldType.Dual: case PlayfieldType.Dual:
return new DualStageVariantGenerator(getDualStageKeyCount(variant)).GenerateMappings(); return new DualStageVariantGenerator(getDualStageKeyCount(variant)).GenerateMappings();
} }
return Array.Empty<KeyBinding>(); return Array.Empty<KeyBinding>();
} }
public override LocalisableString GetVariantName(int variant) public override LocalisableString GetVariantName(int variant)
{ {
switch (getPlayfieldType(variant)) switch (getPlayfieldType(variant))
{ {
default: default:
return $"{variant}K"; return $"{variant}K";
case PlayfieldType.Dual: case PlayfieldType.Dual:
{ {
int keys = getDualStageKeyCount(variant); int keys = getDualStageKeyCount(variant);
return $"{keys}K + {keys}K"; return $"{keys}K + {keys}K";
} }
} }
} }
/// <summary> /// <summary>
/// Finds the number of keys for each stage in a <see cref="PlayfieldType.Dual"/> variant. /// Finds the number of keys for each stage in a <see cref="PlayfieldType.Dual"/> variant.
/// </summary> /// </summary>
/// <param name="variant">The variant.</param> /// <param name="variant">The variant.</param>
private int getDualStageKeyCount(int variant) => (variant - (int)PlayfieldType.Dual) / 2; private int getDualStageKeyCount(int variant) => (variant - (int)PlayfieldType.Dual) / 2;
/// <summary> /// <summary>
/// Finds the <see cref="PlayfieldType"/> that corresponds to a variant value. /// Finds the <see cref="PlayfieldType"/> that corresponds to a variant value.
/// </summary> /// </summary>
/// <param name="variant">The variant value.</param> /// <param name="variant">The variant value.</param>
/// <returns>The <see cref="PlayfieldType"/> that corresponds to <paramref name="variant"/>.</returns> /// <returns>The <see cref="PlayfieldType"/> that corresponds to <paramref name="variant"/>.</returns>
private PlayfieldType getPlayfieldType(int variant) private PlayfieldType getPlayfieldType(int variant)
{ {
return (PlayfieldType)Enum.GetValues(typeof(PlayfieldType)).Cast<int>().OrderDescending().First(v => variant >= v); return (PlayfieldType)Enum.GetValues(typeof(PlayfieldType)).Cast<int>().OrderDescending().First(v => variant >= v);
} }
protected override IEnumerable<HitResult> GetValidHitResults() protected override IEnumerable<HitResult> GetValidHitResults()
{ {
return new[] return new[]
{ {
HitResult.Perfect, HitResult.Perfect,
HitResult.Great, HitResult.Great,
HitResult.Good, HitResult.Good,
HitResult.Ok, HitResult.Ok,
HitResult.Meh, HitResult.Meh,
// HitResult.SmallBonus is used for awarding perfect bonus score but is not included here as // HitResult.SmallBonus is used for awarding perfect bonus score but is not included here as
// it would be a bit redundant to show this to the user. // it would be a bit redundant to show this to the user.
}; };
} }
public override StatisticItem[] CreateStatisticsForScore(ScoreInfo score, IBeatmap playableBeatmap) => new[] public override StatisticItem[] CreateStatisticsForScore(ScoreInfo score, IBeatmap playableBeatmap) => new[]
{ {
new StatisticItem("Performance Breakdown", () => new PerformanceBreakdownChart(score, playableBeatmap) new StatisticItem("Performance Breakdown", () => new PerformanceBreakdownChart(score, playableBeatmap)
{ {
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y AutoSizeAxes = Axes.Y
}), }),
new StatisticItem("Timing Distribution", () => new HitEventTimingDistributionGraph(score.HitEvents) new StatisticItem("Timing Distribution", () => new HitEventTimingDistributionGraph(score.HitEvents)
{ {
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
Height = 250 Height = 250
}, true), }, true),
new StatisticItem("Statistics", () => new SimpleStatisticTable(2, new SimpleStatisticItem[] new StatisticItem("Statistics", () => new SimpleStatisticTable(2, new SimpleStatisticItem[]
{ {
new AverageHitError(score.HitEvents), new AverageHitError(score.HitEvents),
new UnstableRate(score.HitEvents) new UnstableRate(score.HitEvents)
}), true) }), true)
}; };
public override IRulesetFilterCriteria CreateRulesetFilterCriteria() public override IRulesetFilterCriteria CreateRulesetFilterCriteria()
{ {
return new ManiaFilterCriteria(); return new ManiaFilterCriteria();
} }
public override IEnumerable<Drawable> CreateEditorSetupSections() => public override IEnumerable<Drawable> CreateEditorSetupSections() =>
[ [
new MetadataSection(), new MetadataSection(),
new ManiaDifficultySection(), new ManiaDifficultySection(),
new ResourcesSection(), new ResourcesSection(),
new DesignSection(), new DesignSection(),
]; ];
public int GetKeyCount(IBeatmapInfo beatmapInfo, IReadOnlyList<Mod>? mods = null) public int GetKeyCount(IBeatmapInfo beatmapInfo, IReadOnlyList<Mod>? mods = null)
=> ManiaBeatmapConverter.GetColumnCount(LegacyBeatmapConversionDifficultyInfo.FromBeatmapInfo(beatmapInfo), mods); => ManiaBeatmapConverter.GetColumnCount(LegacyBeatmapConversionDifficultyInfo.FromBeatmapInfo(beatmapInfo), mods);
} }
public enum PlayfieldType public enum PlayfieldType
{ {
/// <summary> /// <summary>
/// Columns are grouped into a single stage. /// Columns are grouped into a single stage.
/// Number of columns in this stage lies at (item - Single). /// Number of columns in this stage lies at (item - Single).
/// </summary> /// </summary>
Single = 0, Single = 0,
/// <summary> /// <summary>
/// Columns are grouped into two stages. /// Columns are grouped into two stages.
/// Overall number of columns lies at (item - Dual), further computation is required for /// Overall number of columns lies at (item - Dual), further computation is required for
/// number of columns in each individual stage. /// number of columns in each individual stage.
/// </summary> /// </summary>
Dual = 1000, Dual = 1000,
} }
} }

View File

@ -0,0 +1,40 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.4
using System;
using System.Linq;
using osu.Framework.Localisation;
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Mania.Mods
{
public class ManiaModFullPerfect : ManiaModPerfect
{
public override string Name => "Full Perfect";
public override string Acronym => "FP";
public override LocalisableString Description => @"Placeholder";
public override double ScoreMultiplier => 1;
public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[]
{
typeof(ManiaModPerfect),
}).ToArray();
protected override bool FailCondition(HealthProcessor healthProcessor, JudgementResult result)
{
if (!isRelevantResult(result.Judgement.MinResult) && !isRelevantResult(result.Judgement.MaxResult) && !isRelevantResult(result.Type))
return false;
if (result.Judgement.MaxResult == HitResult.Perfect)
return result.Type < HitResult.Perfect;
return result.Type != result.Judgement.MaxResult;
}
private bool isRelevantResult(HitResult result) => result.AffectsAccuracy() || result.AffectsCombo();
}
}