1
0
mirror of https://github.com/ppy/osu.git synced 2024-09-22 01:27:29 +08:00

Merge pull request #26140 from CaffeeLake/multiplier1x

Fix mod score multiplier rounding to 1.00x with specific mod combinations
This commit is contained in:
Dean Herbert 2024-01-04 19:26:49 +09:00 committed by GitHub
commit 35b9940c4e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 56 additions and 7 deletions

View File

@ -310,6 +310,26 @@ namespace osu.Game.Tests.Mods
Assert.That(invalid?.Select(t => t.GetType()), Is.EquivalentTo(expectedInvalid)); Assert.That(invalid?.Select(t => t.GetType()), Is.EquivalentTo(expectedInvalid));
} }
[Test]
public void TestFormatScoreMultiplier()
{
Assert.AreEqual(ModUtils.FormatScoreMultiplier(0.9999).ToString(), "0.99x");
Assert.AreEqual(ModUtils.FormatScoreMultiplier(1.0).ToString(), "1.00x");
Assert.AreEqual(ModUtils.FormatScoreMultiplier(1.0001).ToString(), "1.01x");
Assert.AreEqual(ModUtils.FormatScoreMultiplier(0.899999999999999).ToString(), "0.90x");
Assert.AreEqual(ModUtils.FormatScoreMultiplier(0.9).ToString(), "0.90x");
Assert.AreEqual(ModUtils.FormatScoreMultiplier(0.900000000000001).ToString(), "0.90x");
Assert.AreEqual(ModUtils.FormatScoreMultiplier(1.099999999999999).ToString(), "1.10x");
Assert.AreEqual(ModUtils.FormatScoreMultiplier(1.1).ToString(), "1.10x");
Assert.AreEqual(ModUtils.FormatScoreMultiplier(1.100000000000001).ToString(), "1.10x");
Assert.AreEqual(ModUtils.FormatScoreMultiplier(1.045).ToString(), "1.05x");
Assert.AreEqual(ModUtils.FormatScoreMultiplier(1.05).ToString(), "1.05x");
Assert.AreEqual(ModUtils.FormatScoreMultiplier(1.055).ToString(), "1.06x");
}
public abstract class CustomMod1 : Mod, IModCompatibilitySpecification public abstract class CustomMod1 : Mod, IModCompatibilitySpecification
{ {
} }
@ -339,6 +359,16 @@ namespace osu.Game.Tests.Mods
public override bool ValidForMultiplayerAsFreeMod => false; public override bool ValidForMultiplayerAsFreeMod => false;
} }
public class EditableMod : Mod
{
public override string Name => string.Empty;
public override LocalisableString Description => string.Empty;
public override string Acronym => string.Empty;
public override double ScoreMultiplier => Multiplier;
public double Multiplier = 1;
}
public interface IModCompatibilitySpecification public interface IModCompatibilitySpecification
{ {
} }

View File

@ -9,6 +9,7 @@ using osu.Game.Graphics.Sprites;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Osu.Mods; using osu.Game.Rulesets.Osu.Mods;
using osu.Game.Screens.Select; using osu.Game.Screens.Select;
using osu.Game.Utils;
namespace osu.Game.Tests.Visual.UserInterface namespace osu.Game.Tests.Visual.UserInterface
{ {
@ -74,7 +75,7 @@ namespace osu.Game.Tests.Visual.UserInterface
private bool assertModsMultiplier(IEnumerable<Mod> mods) private bool assertModsMultiplier(IEnumerable<Mod> mods)
{ {
double multiplier = mods.Aggregate(1.0, (current, mod) => current * mod.ScoreMultiplier); double multiplier = mods.Aggregate(1.0, (current, mod) => current * mod.ScoreMultiplier);
string expectedValue = multiplier.Equals(1.0) ? string.Empty : $"{multiplier:N2}x"; string expectedValue = multiplier == 1 ? string.Empty : ModUtils.FormatScoreMultiplier(multiplier).ToString();
return expectedValue == footerButtonMods.MultiplierText.Current.Value; return expectedValue == footerButtonMods.MultiplierText.Current.Value;
} }

View File

@ -4,7 +4,6 @@
using System; using System;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Extensions.LocalisationExtensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
@ -15,6 +14,7 @@ using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterface;
using osu.Game.Localisation; using osu.Game.Localisation;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
using osu.Game.Utils;
using osuTK; using osuTK;
namespace osu.Game.Overlays.Mods namespace osu.Game.Overlays.Mods
@ -147,7 +147,7 @@ namespace osu.Game.Overlays.Mods
{ {
protected override double RollingDuration => 500; protected override double RollingDuration => 500;
protected override LocalisableString FormatCount(double count) => count.ToLocalisableString(@"0.00x"); protected override LocalisableString FormatCount(double count) => ModUtils.FormatScoreMultiplier(count);
protected override OsuSpriteText CreateSpriteText() => new OsuSpriteText protected override OsuSpriteText CreateSpriteText() => new OsuSpriteText
{ {

View File

@ -19,6 +19,7 @@ using osu.Game.Graphics.Sprites;
using osuTK; using osuTK;
using osuTK.Graphics; using osuTK.Graphics;
using osu.Game.Input.Bindings; using osu.Game.Input.Bindings;
using osu.Game.Utils;
namespace osu.Game.Screens.Select namespace osu.Game.Screens.Select
{ {
@ -87,12 +88,11 @@ namespace osu.Game.Screens.Select
private void updateMultiplierText() => Schedule(() => private void updateMultiplierText() => Schedule(() =>
{ {
double multiplier = Current.Value?.Aggregate(1.0, (current, mod) => current * mod.ScoreMultiplier) ?? 1; double multiplier = Current.Value?.Aggregate(1.0, (current, mod) => current * mod.ScoreMultiplier) ?? 1;
MultiplierText.Text = multiplier == 1 ? string.Empty : ModUtils.FormatScoreMultiplier(multiplier);
MultiplierText.Text = multiplier.Equals(1.0) ? string.Empty : $"{multiplier:N2}x"; if (multiplier > 1)
if (multiplier > 1.0)
MultiplierText.FadeColour(highMultiplierColour, 200); MultiplierText.FadeColour(highMultiplierColour, 200);
else if (multiplier < 1.0) else if (multiplier < 1)
MultiplierText.FadeColour(lowMultiplierColour, 200); MultiplierText.FadeColour(lowMultiplierColour, 200);
else else
MultiplierText.FadeColour(Color4.White, 200); MultiplierText.FadeColour(Color4.White, 200);

View File

@ -5,6 +5,8 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Linq; using System.Linq;
using osu.Framework.Extensions.LocalisationExtensions;
using osu.Framework.Localisation;
using osu.Game.Online.API; using osu.Game.Online.API;
using osu.Game.Rulesets; using osu.Game.Rulesets;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
@ -226,5 +228,21 @@ namespace osu.Game.Utils
return proposedWereValid; return proposedWereValid;
} }
/// <summary>
/// Given a value of a score multiplier, returns a string version with special handling for a value near 1.00x.
/// </summary>
/// <param name="scoreMultiplier">The value of the score multiplier.</param>
/// <returns>A formatted score multiplier with a trailing "x" symbol</returns>
public static LocalisableString FormatScoreMultiplier(double scoreMultiplier)
{
// Round multiplier values away from 1.00x to two significant digits.
if (scoreMultiplier > 1)
scoreMultiplier = Math.Ceiling(Math.Round(scoreMultiplier * 100, 12)) / 100;
else
scoreMultiplier = Math.Floor(Math.Round(scoreMultiplier * 100, 12)) / 100;
return scoreMultiplier.ToLocalisableString("0.00x");
}
} }
} }