mirror of
https://github.com/ppy/osu.git
synced 2024-12-14 16:52:54 +08:00
Merge pull request #25945 from smoogipoo/mania-scorev2-values
Adjust mania scoring to be more in line with ScoreV2 + 85% acc / 15% combo
This commit is contained in:
commit
c23dd1f808
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Utils;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets.Mania.Mods;
|
using osu.Game.Rulesets.Mania.Mods;
|
||||||
using osu.Game.Rulesets.Mania.Objects;
|
using osu.Game.Rulesets.Mania.Objects;
|
||||||
@ -25,8 +26,8 @@ namespace osu.Game.Rulesets.Mania.Tests.Mods
|
|||||||
public void TestHitWindowWithoutDoubleTime() => CreateModTest(new ModTestData
|
public void TestHitWindowWithoutDoubleTime() => CreateModTest(new ModTestData
|
||||||
{
|
{
|
||||||
PassCondition = () => Player.ScoreProcessor.JudgedHits > 0
|
PassCondition = () => Player.ScoreProcessor.JudgedHits > 0
|
||||||
&& Player.ScoreProcessor.Accuracy.Value == 1
|
&& Precision.AlmostEquals(Player.ScoreProcessor.Accuracy.Value, 0.9836, 0.01)
|
||||||
&& Player.ScoreProcessor.TotalScore.Value == 1_000_000,
|
&& Player.ScoreProcessor.TotalScore.Value == 946_049,
|
||||||
Autoplay = false,
|
Autoplay = false,
|
||||||
Beatmap = new Beatmap
|
Beatmap = new Beatmap
|
||||||
{
|
{
|
||||||
@ -53,7 +54,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Mods
|
|||||||
Mod = doubleTime,
|
Mod = doubleTime,
|
||||||
PassCondition = () => Player.ScoreProcessor.JudgedHits > 0
|
PassCondition = () => Player.ScoreProcessor.JudgedHits > 0
|
||||||
&& Player.ScoreProcessor.Accuracy.Value == 1
|
&& Player.ScoreProcessor.Accuracy.Value == 1
|
||||||
&& Player.ScoreProcessor.TotalScore.Value == (long)(1_000_010 * doubleTime.ScoreMultiplier),
|
&& Player.ScoreProcessor.TotalScore.Value == (long)(1_000_000 * doubleTime.ScoreMultiplier),
|
||||||
Autoplay = false,
|
Autoplay = false,
|
||||||
Beatmap = new Beatmap
|
Beatmap = new Beatmap
|
||||||
{
|
{
|
||||||
|
@ -200,12 +200,10 @@ namespace osu.Game.Rulesets.Mania.Tests
|
|||||||
});
|
});
|
||||||
|
|
||||||
assertHeadJudgement(HitResult.Perfect);
|
assertHeadJudgement(HitResult.Perfect);
|
||||||
// judgement combo offset by perfect bonus judgement. see logic in DrawableNote.CheckForResult.
|
assertComboAtJudgement(0, 1);
|
||||||
assertComboAtJudgement(1, 1);
|
|
||||||
assertTailJudgement(HitResult.Meh);
|
assertTailJudgement(HitResult.Meh);
|
||||||
assertComboAtJudgement(2, 0);
|
assertComboAtJudgement(1, 0);
|
||||||
// judgement combo offset by perfect bonus judgement. see logic in DrawableNote.CheckForResult.
|
assertComboAtJudgement(3, 1);
|
||||||
assertComboAtJudgement(4, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -54,7 +54,7 @@ namespace osu.Game.Rulesets.Mania.Tests
|
|||||||
AddAssert("all objects perfectly judged",
|
AddAssert("all objects perfectly judged",
|
||||||
() => judgementResults.Select(result => result.Type),
|
() => judgementResults.Select(result => result.Type),
|
||||||
() => Is.EquivalentTo(judgementResults.Select(result => result.Judgement.MaxResult)));
|
() => Is.EquivalentTo(judgementResults.Select(result => result.Judgement.MaxResult)));
|
||||||
AddAssert("score is correct", () => currentPlayer.ScoreProcessor.TotalScore.Value, () => Is.EqualTo(1_000_030));
|
AddAssert("score is correct", () => currentPlayer.ScoreProcessor.TotalScore.Value, () => Is.EqualTo(1_000_000));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -87,7 +87,7 @@ namespace osu.Game.Rulesets.Mania.Tests
|
|||||||
AddAssert("all objects perfectly judged",
|
AddAssert("all objects perfectly judged",
|
||||||
() => judgementResults.Select(result => result.Type),
|
() => judgementResults.Select(result => result.Type),
|
||||||
() => Is.EquivalentTo(judgementResults.Select(result => result.Judgement.MaxResult)));
|
() => Is.EquivalentTo(judgementResults.Select(result => result.Judgement.MaxResult)));
|
||||||
AddAssert("score is correct", () => currentPlayer.ScoreProcessor.TotalScore.Value, () => Is.EqualTo(1_000_040));
|
AddAssert("score is correct", () => currentPlayer.ScoreProcessor.TotalScore.Value, () => Is.EqualTo(1_000_000));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void performTest(List<ManiaHitObject> hitObjects, List<ReplayFrame> frames)
|
private void performTest(List<ManiaHitObject> hitObjects, List<ReplayFrame> frames)
|
||||||
|
@ -13,8 +13,6 @@ using osu.Game.Beatmaps;
|
|||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Rulesets.Mania.Configuration;
|
using osu.Game.Rulesets.Mania.Configuration;
|
||||||
using osu.Game.Rulesets.Mania.Skinning.Default;
|
using osu.Game.Rulesets.Mania.Skinning.Default;
|
||||||
using osu.Game.Rulesets.Objects;
|
|
||||||
using osu.Game.Rulesets.Objects.Drawables;
|
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
using osu.Game.Rulesets.UI.Scrolling;
|
using osu.Game.Rulesets.UI.Scrolling;
|
||||||
using osu.Game.Screens.Edit;
|
using osu.Game.Screens.Edit;
|
||||||
@ -40,8 +38,6 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
|||||||
|
|
||||||
private Drawable headPiece;
|
private Drawable headPiece;
|
||||||
|
|
||||||
private DrawableNotePerfectBonus perfectBonus;
|
|
||||||
|
|
||||||
public DrawableNote()
|
public DrawableNote()
|
||||||
: this(null)
|
: this(null)
|
||||||
{
|
{
|
||||||
@ -93,10 +89,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
|||||||
if (!userTriggered)
|
if (!userTriggered)
|
||||||
{
|
{
|
||||||
if (!HitObject.HitWindows.CanBeHit(timeOffset))
|
if (!HitObject.HitWindows.CanBeHit(timeOffset))
|
||||||
{
|
|
||||||
perfectBonus.TriggerResult(false);
|
|
||||||
ApplyResult(r => r.Type = r.Judgement.MinResult);
|
ApplyResult(r => r.Type = r.Judgement.MinResult);
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -107,16 +100,9 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
|||||||
|
|
||||||
result = GetCappedResult(result);
|
result = GetCappedResult(result);
|
||||||
|
|
||||||
perfectBonus.TriggerResult(result == HitResult.Perfect);
|
|
||||||
ApplyResult(r => r.Type = result);
|
ApplyResult(r => r.Type = result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void MissForcefully()
|
|
||||||
{
|
|
||||||
perfectBonus.TriggerResult(false);
|
|
||||||
base.MissForcefully();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Some objects in mania may want to limit the max result.
|
/// Some objects in mania may want to limit the max result.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -137,32 +123,6 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void AddNestedHitObject(DrawableHitObject hitObject)
|
|
||||||
{
|
|
||||||
switch (hitObject)
|
|
||||||
{
|
|
||||||
case DrawableNotePerfectBonus bonus:
|
|
||||||
AddInternal(perfectBonus = bonus);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void ClearNestedHitObjects()
|
|
||||||
{
|
|
||||||
RemoveInternal(perfectBonus, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override DrawableHitObject CreateNestedHitObject(HitObject hitObject)
|
|
||||||
{
|
|
||||||
switch (hitObject)
|
|
||||||
{
|
|
||||||
case NotePerfectBonus bonus:
|
|
||||||
return new DrawableNotePerfectBonus(bonus);
|
|
||||||
}
|
|
||||||
|
|
||||||
return base.CreateNestedHitObject(hitObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateSnapColour()
|
private void updateSnapColour()
|
||||||
{
|
{
|
||||||
if (beatmap == null || HitObject == null) return;
|
if (beatmap == null || HitObject == null) return;
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
// 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.
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
|
||||||
{
|
|
||||||
public partial class DrawableNotePerfectBonus : DrawableManiaHitObject<NotePerfectBonus>
|
|
||||||
{
|
|
||||||
public override bool DisplayResult => false;
|
|
||||||
|
|
||||||
public DrawableNotePerfectBonus()
|
|
||||||
: this(null!)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public DrawableNotePerfectBonus(NotePerfectBonus hitObject)
|
|
||||||
: base(hitObject)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Apply a judgement result.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="hit">Whether this tick was reached.</param>
|
|
||||||
internal void TriggerResult(bool hit) => ApplyResult(r => r.Type = hit ? r.Judgement.MaxResult : r.Judgement.MinResult);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,7 +1,6 @@
|
|||||||
// 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.Threading;
|
|
||||||
using osu.Game.Rulesets.Judgements;
|
using osu.Game.Rulesets.Judgements;
|
||||||
using osu.Game.Rulesets.Mania.Judgements;
|
using osu.Game.Rulesets.Mania.Judgements;
|
||||||
|
|
||||||
@ -13,12 +12,5 @@ namespace osu.Game.Rulesets.Mania.Objects
|
|||||||
public class Note : ManiaHitObject
|
public class Note : ManiaHitObject
|
||||||
{
|
{
|
||||||
public override Judgement CreateJudgement() => new ManiaJudgement();
|
public override Judgement CreateJudgement() => new ManiaJudgement();
|
||||||
|
|
||||||
protected override void CreateNestedHitObjects(CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
base.CreateNestedHitObjects(cancellationToken);
|
|
||||||
|
|
||||||
AddNested(new NotePerfectBonus { StartTime = StartTime });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,20 +0,0 @@
|
|||||||
// 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.
|
|
||||||
|
|
||||||
using osu.Game.Rulesets.Judgements;
|
|
||||||
using osu.Game.Rulesets.Mania.Judgements;
|
|
||||||
using osu.Game.Rulesets.Scoring;
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Mania.Objects
|
|
||||||
{
|
|
||||||
public class NotePerfectBonus : ManiaHitObject
|
|
||||||
{
|
|
||||||
public override Judgement CreateJudgement() => new NotePerfectBonusJudgement();
|
|
||||||
protected override HitWindows CreateHitWindows() => HitWindows.Empty;
|
|
||||||
|
|
||||||
public class NotePerfectBonusJudgement : ManiaJudgement
|
|
||||||
{
|
|
||||||
public override HitResult MaxResult => HitResult.SmallBonus;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -26,13 +26,50 @@ namespace osu.Game.Rulesets.Mania.Scoring
|
|||||||
|
|
||||||
protected override double ComputeTotalScore(double comboProgress, double accuracyProgress, double bonusPortion)
|
protected override double ComputeTotalScore(double comboProgress, double accuracyProgress, double bonusPortion)
|
||||||
{
|
{
|
||||||
return 10000 * comboProgress
|
return 150000 * comboProgress
|
||||||
+ 990000 * Math.Pow(Accuracy.Value, 2 + 2 * Accuracy.Value) * accuracyProgress
|
+ 850000 * Math.Pow(Accuracy.Value, 2 + 2 * Accuracy.Value) * accuracyProgress
|
||||||
+ bonusPortion;
|
+ bonusPortion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override double GetNumericResultFor(JudgementResult result)
|
||||||
|
{
|
||||||
|
switch (result.Type)
|
||||||
|
{
|
||||||
|
case HitResult.Perfect:
|
||||||
|
return 305;
|
||||||
|
}
|
||||||
|
|
||||||
|
return base.GetNumericResultFor(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override double GetMaxNumericResultFor(JudgementResult result)
|
||||||
|
{
|
||||||
|
switch (result.Judgement.MaxResult)
|
||||||
|
{
|
||||||
|
case HitResult.Perfect:
|
||||||
|
return 305;
|
||||||
|
}
|
||||||
|
|
||||||
|
return base.GetMaxNumericResultFor(result);
|
||||||
|
}
|
||||||
|
|
||||||
protected override double GetComboScoreChange(JudgementResult result)
|
protected override double GetComboScoreChange(JudgementResult result)
|
||||||
=> GetNumericResultFor(result) * Math.Min(Math.Max(0.5, Math.Log(result.ComboAfterJudgement, combo_base)), Math.Log(400, combo_base));
|
{
|
||||||
|
double numericResult;
|
||||||
|
|
||||||
|
switch (result.Type)
|
||||||
|
{
|
||||||
|
case HitResult.Perfect:
|
||||||
|
numericResult = 300;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
numericResult = GetNumericResultFor(result);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return numericResult * Math.Min(Math.Max(0.5, Math.Log(result.ComboAfterJudgement, combo_base)), Math.Log(400, combo_base));
|
||||||
|
}
|
||||||
|
|
||||||
private class JudgementOrderComparer : IComparer<HitObject>
|
private class JudgementOrderComparer : IComparer<HitObject>
|
||||||
{
|
{
|
||||||
|
@ -109,7 +109,6 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
TopLevelContainer.Add(HitObjectArea.Explosions.CreateProxy());
|
TopLevelContainer.Add(HitObjectArea.Explosions.CreateProxy());
|
||||||
|
|
||||||
RegisterPool<Note, DrawableNote>(10, 50);
|
RegisterPool<Note, DrawableNote>(10, 50);
|
||||||
RegisterPool<NotePerfectBonus, DrawableNotePerfectBonus>(10, 50);
|
|
||||||
RegisterPool<HoldNote, DrawableHoldNote>(10, 50);
|
RegisterPool<HoldNote, DrawableHoldNote>(10, 50);
|
||||||
RegisterPool<HeadNote, DrawableHoldNoteHead>(10, 50);
|
RegisterPool<HeadNote, DrawableHoldNoteHead>(10, 50);
|
||||||
RegisterPool<TailNote, DrawableHoldNoteTail>(10, 50);
|
RegisterPool<TailNote, DrawableHoldNoteTail>(10, 50);
|
||||||
|
@ -377,8 +377,8 @@ namespace osu.Game.Database
|
|||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
return (long)Math.Round((
|
return (long)Math.Round((
|
||||||
990000 * comboProportion
|
850000 * comboProportion
|
||||||
+ 10000 * Math.Pow(score.Accuracy, 2 + 2 * score.Accuracy)
|
+ 150000 * Math.Pow(score.Accuracy, 2 + 2 * score.Accuracy)
|
||||||
+ bonusProportion) * modMultiplier);
|
+ bonusProportion) * modMultiplier);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -33,9 +33,10 @@ namespace osu.Game.Scoring.Legacy
|
|||||||
/// <item><description>30000004: Fixed mod multipliers during legacy score conversion. Reconvert all scores.</description></item>
|
/// <item><description>30000004: Fixed mod multipliers during legacy score conversion. Reconvert all scores.</description></item>
|
||||||
/// <item><description>30000005: Introduce combo exponent in the osu! gamemode. Reconvert all scores.</description></item>
|
/// <item><description>30000005: Introduce combo exponent in the osu! gamemode. Reconvert all scores.</description></item>
|
||||||
/// <item><description>30000006: Fix edge cases in conversion after combo exponent introduction that lead to NaNs. Reconvert all scores.</description></item>
|
/// <item><description>30000006: Fix edge cases in conversion after combo exponent introduction that lead to NaNs. Reconvert all scores.</description></item>
|
||||||
|
/// <item><description>30000007: Adjust osu!mania combo and accuracy portions and judgement scoring values. Reconvert all scores.</description></item>
|
||||||
/// </list>
|
/// </list>
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public const int LATEST_VERSION = 30000006;
|
public const int LATEST_VERSION = 30000007;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The first stable-compatible YYYYMMDD format version given to lazer usage of replays.
|
/// The first stable-compatible YYYYMMDD format version given to lazer usage of replays.
|
||||||
|
Loading…
Reference in New Issue
Block a user