mirror of
https://github.com/ppy/osu.git
synced 2024-09-21 20:07:25 +08:00
Remove ScoreManager.Mode, handle per-use
This commit is contained in:
parent
829e47d30b
commit
510b8e4c78
@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Scoring
|
|||||||
{
|
{
|
||||||
public abstract partial class ScoreProcessor : JudgementProcessor
|
public abstract partial class ScoreProcessor : JudgementProcessor
|
||||||
{
|
{
|
||||||
protected const double MAX_SCORE = 1000000;
|
public const double MAX_SCORE = 1000000;
|
||||||
|
|
||||||
private const double accuracy_cutoff_x = 1;
|
private const double accuracy_cutoff_x = 1;
|
||||||
private const double accuracy_cutoff_s = 0.95;
|
private const double accuracy_cutoff_s = 0.95;
|
||||||
@ -76,11 +76,6 @@ namespace osu.Game.Rulesets.Scoring
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly BindableInt HighestCombo = new BindableInt();
|
public readonly BindableInt HighestCombo = new BindableInt();
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The <see cref="ScoringMode"/> used to calculate scores.
|
|
||||||
/// </summary>
|
|
||||||
public readonly Bindable<ScoringMode> Mode = new Bindable<ScoringMode>();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The <see cref="HitEvent"/>s collected during gameplay thus far.
|
/// The <see cref="HitEvent"/>s collected during gameplay thus far.
|
||||||
/// Intended for use with various statistics displays.
|
/// Intended for use with various statistics displays.
|
||||||
@ -173,7 +168,6 @@ namespace osu.Game.Rulesets.Scoring
|
|||||||
Rank.Value = mod.AdjustRank(Rank.Value, accuracy.NewValue);
|
Rank.Value = mod.AdjustRank(Rank.Value, accuracy.NewValue);
|
||||||
};
|
};
|
||||||
|
|
||||||
Mode.ValueChanged += _ => updateScore();
|
|
||||||
Mods.ValueChanged += mods =>
|
Mods.ValueChanged += mods =>
|
||||||
{
|
{
|
||||||
ScoreMultiplier = 1;
|
ScoreMultiplier = 1;
|
||||||
@ -278,45 +272,7 @@ namespace osu.Game.Rulesets.Scoring
|
|||||||
private void updateScore()
|
private void updateScore()
|
||||||
{
|
{
|
||||||
Accuracy.Value = currentMaxBasicScore > 0 ? currentBasicScore / currentMaxBasicScore : 1;
|
Accuracy.Value = currentMaxBasicScore > 0 ? currentBasicScore / currentMaxBasicScore : 1;
|
||||||
|
TotalScore.Value = (long)Math.Round(ComputeTotalScore());
|
||||||
long standardisedScore = (long)Math.Round(ComputeTotalScore());
|
|
||||||
|
|
||||||
TotalScore.Value = Mode.Value == ScoringMode.Standardised
|
|
||||||
? standardisedScore
|
|
||||||
: convertToClassic(standardisedScore, MaxBasicJudgements, ClassicScoreMultiplier);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Retrieves the total score from a <see cref="ScoreInfo"/> in the given scoring mode.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="mode">The mode to return the total score in.</param>
|
|
||||||
/// <param name="scoreInfo">The score to get the total score of.</param>
|
|
||||||
/// <returns>The total score.</returns>
|
|
||||||
public long ComputeScore(ScoringMode mode, ScoreInfo scoreInfo)
|
|
||||||
{
|
|
||||||
int maxBasicJudgements = scoreInfo.MaximumStatistics.Where(k => k.Key.IsBasic())
|
|
||||||
.Select(k => k.Value)
|
|
||||||
.DefaultIfEmpty(0)
|
|
||||||
.Sum();
|
|
||||||
|
|
||||||
return mode == ScoringMode.Standardised
|
|
||||||
? scoreInfo.TotalScore
|
|
||||||
: convertToClassic(scoreInfo.TotalScore, maxBasicJudgements, ClassicScoreMultiplier);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Converts a standardised total score to the classic score.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="score">The standardised score.</param>
|
|
||||||
/// <param name="maxBasicJudgements">The maximum possible number of basic judgements.</param>
|
|
||||||
/// <param name="classicMultiplier">The classic multiplier.</param>
|
|
||||||
/// <returns>The classic score.</returns>
|
|
||||||
private static long convertToClassic(long score, int maxBasicJudgements, double classicMultiplier)
|
|
||||||
{
|
|
||||||
// This gives a similar feeling to osu!stable scoring (ScoreV1) while keeping classic scoring as only a constant multiple of standardised scoring.
|
|
||||||
// The invariant is important to ensure that scores don't get re-ordered on leaderboards between the two scoring modes.
|
|
||||||
double scaledRawScore = score / MAX_SCORE;
|
|
||||||
return (long)Math.Round(Math.Pow(scaledRawScore * Math.Max(1, maxBasicJudgements), 2) * classicMultiplier);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract double ComputeTotalScore();
|
protected abstract double ComputeTotalScore();
|
||||||
|
@ -3,13 +3,58 @@
|
|||||||
|
|
||||||
#nullable disable
|
#nullable disable
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
|
|
||||||
namespace osu.Game.Scoring.Legacy
|
namespace osu.Game.Scoring.Legacy
|
||||||
{
|
{
|
||||||
public static class ScoreInfoExtensions
|
public static class ScoreInfoExtensions
|
||||||
{
|
{
|
||||||
|
public static long GetDisplayScore(this ScoreProcessor scoreProcessor, ScoringMode mode)
|
||||||
|
=> getDisplayScore(scoreProcessor.Ruleset.RulesetInfo.OnlineID, scoreProcessor.TotalScore.Value, mode, scoreProcessor.MaximumStatistics);
|
||||||
|
|
||||||
|
public static long GetDisplayScore(this ScoreInfo scoreInfo, ScoringMode mode)
|
||||||
|
=> getDisplayScore(scoreInfo.Ruleset.OnlineID, scoreInfo.TotalScore, mode, scoreInfo.MaximumStatistics);
|
||||||
|
|
||||||
|
private static long getDisplayScore(int rulesetId, long score, ScoringMode mode, IReadOnlyDictionary<HitResult, int> maximumStatistics)
|
||||||
|
{
|
||||||
|
if (mode == ScoringMode.Standardised)
|
||||||
|
return score;
|
||||||
|
|
||||||
|
double multiplier;
|
||||||
|
|
||||||
|
switch (rulesetId)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
multiplier = 36;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
multiplier = 22;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
multiplier = 28;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
multiplier = 16;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return score;
|
||||||
|
}
|
||||||
|
|
||||||
|
int maxBasicJudgements = maximumStatistics.Where(k => k.Key.IsBasic()).Select(k => k.Value).DefaultIfEmpty(0).Sum();
|
||||||
|
|
||||||
|
// This gives a similar feeling to osu!stable scoring (ScoreV1) while keeping classic scoring as only a constant multiple of standardised scoring.
|
||||||
|
// The invariant is important to ensure that scores don't get re-ordered on leaderboards between the two scoring modes.
|
||||||
|
double scaledRawScore = score / ScoreProcessor.MAX_SCORE;
|
||||||
|
return (long)Math.Round(Math.Pow(scaledRawScore * Math.Max(1, maxBasicJudgements), 2) * multiplier);
|
||||||
|
}
|
||||||
|
|
||||||
public static int? GetCountGeki(this ScoreInfo scoreInfo)
|
public static int? GetCountGeki(this ScoreInfo scoreInfo)
|
||||||
{
|
{
|
||||||
switch (scoreInfo.Ruleset.OnlineID)
|
switch (scoreInfo.Ruleset.OnlineID)
|
||||||
|
@ -20,6 +20,7 @@ using osu.Game.Overlays.Notifications;
|
|||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
using osu.Game.Online.API;
|
using osu.Game.Online.API;
|
||||||
|
using osu.Game.Scoring.Legacy;
|
||||||
|
|
||||||
namespace osu.Game.Scoring
|
namespace osu.Game.Scoring
|
||||||
{
|
{
|
||||||
@ -105,16 +106,7 @@ namespace osu.Game.Scoring
|
|||||||
/// <param name="score">The <see cref="ScoreInfo"/> to calculate the total score of.</param>
|
/// <param name="score">The <see cref="ScoreInfo"/> to calculate the total score of.</param>
|
||||||
/// <param name="mode">The <see cref="ScoringMode"/> to return the total score as.</param>
|
/// <param name="mode">The <see cref="ScoringMode"/> to return the total score as.</param>
|
||||||
/// <returns>The total score.</returns>
|
/// <returns>The total score.</returns>
|
||||||
public long GetTotalScore([NotNull] ScoreInfo score, ScoringMode mode = ScoringMode.Standardised)
|
public long GetTotalScore([NotNull] ScoreInfo score, ScoringMode mode = ScoringMode.Standardised) => score.GetDisplayScore(mode);
|
||||||
{
|
|
||||||
// Shortcut to avoid potentially creating many ruleset objects in the default scoring mode.
|
|
||||||
if (mode == ScoringMode.Standardised)
|
|
||||||
return score.TotalScore;
|
|
||||||
|
|
||||||
return score.Ruleset.CreateInstance()
|
|
||||||
.CreateScoreProcessor()
|
|
||||||
.ComputeScore(mode, score);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Retrieves the maximum achievable combo for the provided score.
|
/// Retrieves the maximum achievable combo for the provided score.
|
||||||
|
@ -11,8 +11,10 @@ using osu.Framework.Extensions.Color4Extensions;
|
|||||||
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;
|
||||||
|
using osu.Game.Configuration;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
|
using osu.Game.Rulesets.Scoring;
|
||||||
using osu.Game.Users;
|
using osu.Game.Users;
|
||||||
using osu.Game.Users.Drawables;
|
using osu.Game.Users.Drawables;
|
||||||
using osu.Game.Utils;
|
using osu.Game.Utils;
|
||||||
@ -55,6 +57,7 @@ namespace osu.Game.Screens.Play.HUD
|
|||||||
public BindableInt Combo { get; } = new BindableInt();
|
public BindableInt Combo { get; } = new BindableInt();
|
||||||
public BindableBool HasQuit { get; } = new BindableBool();
|
public BindableBool HasQuit { get; } = new BindableBool();
|
||||||
public Bindable<long> DisplayOrder { get; } = new Bindable<long>();
|
public Bindable<long> DisplayOrder { get; } = new Bindable<long>();
|
||||||
|
public Func<ScoringMode, long> GetDisplayScore { get; set; }
|
||||||
|
|
||||||
public Color4? BackgroundColour { get; set; }
|
public Color4? BackgroundColour { get; set; }
|
||||||
|
|
||||||
@ -100,6 +103,8 @@ namespace osu.Game.Screens.Play.HUD
|
|||||||
|
|
||||||
private Container scoreComponents;
|
private Container scoreComponents;
|
||||||
|
|
||||||
|
private IBindable<ScoringMode> scoreDisplayMode;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new <see cref="GameplayLeaderboardScore"/>.
|
/// Creates a new <see cref="GameplayLeaderboardScore"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -112,10 +117,12 @@ namespace osu.Game.Screens.Play.HUD
|
|||||||
|
|
||||||
AutoSizeAxes = Axes.X;
|
AutoSizeAxes = Axes.X;
|
||||||
Height = PANEL_HEIGHT;
|
Height = PANEL_HEIGHT;
|
||||||
|
|
||||||
|
GetDisplayScore = _ => TotalScore.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(OsuColour colours)
|
private void load(OsuColour colours, OsuConfigManager osuConfigManager)
|
||||||
{
|
{
|
||||||
Container avatarContainer;
|
Container avatarContainer;
|
||||||
|
|
||||||
@ -286,7 +293,9 @@ namespace osu.Game.Screens.Play.HUD
|
|||||||
|
|
||||||
LoadComponentAsync(new DrawableAvatar(User), avatarContainer.Add);
|
LoadComponentAsync(new DrawableAvatar(User), avatarContainer.Add);
|
||||||
|
|
||||||
TotalScore.BindValueChanged(v => scoreText.Text = v.NewValue.ToString("N0"), true);
|
scoreDisplayMode = osuConfigManager.GetBindable<ScoringMode>(OsuSetting.ScoreDisplayMode);
|
||||||
|
scoreDisplayMode.BindValueChanged(_ => updateScore());
|
||||||
|
TotalScore.BindValueChanged(_ => updateScore(), true);
|
||||||
|
|
||||||
Accuracy.BindValueChanged(v =>
|
Accuracy.BindValueChanged(v =>
|
||||||
{
|
{
|
||||||
@ -303,6 +312,11 @@ namespace osu.Game.Screens.Play.HUD
|
|||||||
HasQuit.BindValueChanged(_ => updateState());
|
HasQuit.BindValueChanged(_ => updateState());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateScore()
|
||||||
|
{
|
||||||
|
scoreText.Text = GetDisplayScore(scoreDisplayMode.Value).ToString("N0");
|
||||||
|
}
|
||||||
|
|
||||||
protected override void LoadComplete()
|
protected override void LoadComplete()
|
||||||
{
|
{
|
||||||
base.LoadComplete();
|
base.LoadComplete();
|
||||||
|
@ -9,12 +9,14 @@ using osu.Framework.Bindables;
|
|||||||
using osu.Game.Configuration;
|
using osu.Game.Configuration;
|
||||||
using osu.Game.Graphics.UserInterface;
|
using osu.Game.Graphics.UserInterface;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
|
using osu.Game.Scoring.Legacy;
|
||||||
|
|
||||||
namespace osu.Game.Screens.Play.HUD
|
namespace osu.Game.Screens.Play.HUD
|
||||||
{
|
{
|
||||||
public abstract partial class GameplayScoreCounter : ScoreCounter
|
public abstract partial class GameplayScoreCounter : ScoreCounter
|
||||||
{
|
{
|
||||||
private Bindable<ScoringMode> scoreDisplayMode;
|
private Bindable<ScoringMode> scoreDisplayMode;
|
||||||
|
private Bindable<long> totalScoreBindable;
|
||||||
|
|
||||||
protected GameplayScoreCounter()
|
protected GameplayScoreCounter()
|
||||||
: base(6)
|
: base(6)
|
||||||
@ -42,7 +44,8 @@ namespace osu.Game.Screens.Play.HUD
|
|||||||
}
|
}
|
||||||
}, true);
|
}, true);
|
||||||
|
|
||||||
Current.BindTo(scoreProcessor.TotalScore);
|
totalScoreBindable = scoreProcessor.TotalScore.GetBoundCopy();
|
||||||
|
totalScoreBindable.BindValueChanged(_ => Current.Value = scoreProcessor.GetDisplayScore(scoreDisplayMode.Value), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,9 @@
|
|||||||
|
|
||||||
#nullable disable
|
#nullable disable
|
||||||
|
|
||||||
|
using System;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Game.Rulesets.Scoring;
|
||||||
|
|
||||||
namespace osu.Game.Screens.Play.HUD
|
namespace osu.Game.Screens.Play.HUD
|
||||||
{
|
{
|
||||||
@ -20,5 +22,7 @@ namespace osu.Game.Screens.Play.HUD
|
|||||||
/// Lower numbers will appear higher in cases of <see cref="TotalScore"/> ties.
|
/// Lower numbers will appear higher in cases of <see cref="TotalScore"/> ties.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Bindable<long> DisplayOrder { get; }
|
Bindable<long> DisplayOrder { get; }
|
||||||
|
|
||||||
|
Func<ScoringMode, long> GetDisplayScore { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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.Collections.Generic;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
@ -10,6 +9,7 @@ using osu.Game.Configuration;
|
|||||||
using osu.Game.Online.API.Requests;
|
using osu.Game.Online.API.Requests;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
using osu.Game.Scoring;
|
using osu.Game.Scoring;
|
||||||
|
using osu.Game.Scoring.Legacy;
|
||||||
using osu.Game.Screens.Select;
|
using osu.Game.Screens.Select;
|
||||||
using osu.Game.Users;
|
using osu.Game.Users;
|
||||||
|
|
||||||
@ -27,15 +27,9 @@ namespace osu.Game.Screens.Play.HUD
|
|||||||
|
|
||||||
public readonly IBindableList<ScoreInfo> Scores = new BindableList<ScoreInfo>();
|
public readonly IBindableList<ScoreInfo> Scores = new BindableList<ScoreInfo>();
|
||||||
|
|
||||||
// hold references to ensure bindables are updated.
|
|
||||||
private readonly List<Bindable<long>> scoreBindables = new List<Bindable<long>>();
|
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private ScoreProcessor scoreProcessor { get; set; } = null!;
|
private ScoreProcessor scoreProcessor { get; set; } = null!;
|
||||||
|
|
||||||
[Resolved]
|
|
||||||
private ScoreManager scoreManager { get; set; } = null!;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether the leaderboard should be visible regardless of the configuration value.
|
/// Whether the leaderboard should be visible regardless of the configuration value.
|
||||||
/// This is true by default, but can be changed.
|
/// This is true by default, but can be changed.
|
||||||
@ -70,7 +64,6 @@ namespace osu.Game.Screens.Play.HUD
|
|||||||
private void showScores()
|
private void showScores()
|
||||||
{
|
{
|
||||||
Clear();
|
Clear();
|
||||||
scoreBindables.Clear();
|
|
||||||
|
|
||||||
if (!Scores.Any())
|
if (!Scores.Any())
|
||||||
return;
|
return;
|
||||||
@ -79,12 +72,8 @@ namespace osu.Game.Screens.Play.HUD
|
|||||||
{
|
{
|
||||||
var score = Add(s.User, false);
|
var score = Add(s.User, false);
|
||||||
|
|
||||||
var bindableTotal = scoreManager.GetBindableTotalScore(s);
|
score.GetDisplayScore = s.GetDisplayScore;
|
||||||
|
score.TotalScore.Value = s.TotalScore;
|
||||||
// Direct binding not possible due to differing types (see https://github.com/ppy/osu/issues/20298).
|
|
||||||
bindableTotal.BindValueChanged(total => score.TotalScore.Value = total.NewValue, true);
|
|
||||||
scoreBindables.Add(bindableTotal);
|
|
||||||
|
|
||||||
score.Accuracy.Value = s.Accuracy;
|
score.Accuracy.Value = s.Accuracy;
|
||||||
score.Combo.Value = s.MaxCombo;
|
score.Combo.Value = s.MaxCombo;
|
||||||
score.DisplayOrder.Value = s.OnlineID > 0 ? s.OnlineID : s.Date.ToUnixTimeSeconds();
|
score.DisplayOrder.Value = s.OnlineID > 0 ? s.OnlineID : s.Date.ToUnixTimeSeconds();
|
||||||
@ -92,6 +81,7 @@ namespace osu.Game.Screens.Play.HUD
|
|||||||
|
|
||||||
ILeaderboardScore local = Add(trackingUser, true);
|
ILeaderboardScore local = Add(trackingUser, true);
|
||||||
|
|
||||||
|
local.GetDisplayScore = scoreProcessor.GetDisplayScore;
|
||||||
local.TotalScore.BindTarget = scoreProcessor.TotalScore;
|
local.TotalScore.BindTarget = scoreProcessor.TotalScore;
|
||||||
local.Accuracy.BindTarget = scoreProcessor.Accuracy;
|
local.Accuracy.BindTarget = scoreProcessor.Accuracy;
|
||||||
local.Combo.BindTarget = scoreProcessor.HighestCombo;
|
local.Combo.BindTarget = scoreProcessor.HighestCombo;
|
||||||
|
@ -237,9 +237,6 @@ namespace osu.Game.Screens.Play
|
|||||||
|
|
||||||
dependencies.CacheAs(HealthProcessor);
|
dependencies.CacheAs(HealthProcessor);
|
||||||
|
|
||||||
if (!ScoreProcessor.Mode.Disabled)
|
|
||||||
config.BindWith(OsuSetting.ScoreDisplayMode, ScoreProcessor.Mode);
|
|
||||||
|
|
||||||
InternalChild = GameplayClockContainer = CreateGameplayClockContainer(Beatmap.Value, DrawableRuleset.GameplayStartTime);
|
InternalChild = GameplayClockContainer = CreateGameplayClockContainer(Beatmap.Value, DrawableRuleset.GameplayStartTime);
|
||||||
|
|
||||||
AddInternal(screenSuspension = new ScreenSuspensionHandler(GameplayClockContainer));
|
AddInternal(screenSuspension = new ScreenSuspensionHandler(GameplayClockContainer));
|
||||||
|
Loading…
Reference in New Issue
Block a user