mirror of
https://github.com/ppy/osu.git
synced 2024-09-21 18:07:23 +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
|
||||
{
|
||||
protected const double MAX_SCORE = 1000000;
|
||||
public const double MAX_SCORE = 1000000;
|
||||
|
||||
private const double accuracy_cutoff_x = 1;
|
||||
private const double accuracy_cutoff_s = 0.95;
|
||||
@ -76,11 +76,6 @@ namespace osu.Game.Rulesets.Scoring
|
||||
/// </summary>
|
||||
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>
|
||||
/// The <see cref="HitEvent"/>s collected during gameplay thus far.
|
||||
/// Intended for use with various statistics displays.
|
||||
@ -173,7 +168,6 @@ namespace osu.Game.Rulesets.Scoring
|
||||
Rank.Value = mod.AdjustRank(Rank.Value, accuracy.NewValue);
|
||||
};
|
||||
|
||||
Mode.ValueChanged += _ => updateScore();
|
||||
Mods.ValueChanged += mods =>
|
||||
{
|
||||
ScoreMultiplier = 1;
|
||||
@ -278,45 +272,7 @@ namespace osu.Game.Rulesets.Scoring
|
||||
private void updateScore()
|
||||
{
|
||||
Accuracy.Value = currentMaxBasicScore > 0 ? currentBasicScore / currentMaxBasicScore : 1;
|
||||
|
||||
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);
|
||||
TotalScore.Value = (long)Math.Round(ComputeTotalScore());
|
||||
}
|
||||
|
||||
protected abstract double ComputeTotalScore();
|
||||
|
@ -3,13 +3,58 @@
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
|
||||
namespace osu.Game.Scoring.Legacy
|
||||
{
|
||||
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)
|
||||
{
|
||||
switch (scoreInfo.Ruleset.OnlineID)
|
||||
|
@ -20,6 +20,7 @@ using osu.Game.Overlays.Notifications;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Scoring.Legacy;
|
||||
|
||||
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="mode">The <see cref="ScoringMode"/> to return the total score as.</param>
|
||||
/// <returns>The total score.</returns>
|
||||
public long GetTotalScore([NotNull] ScoreInfo score, ScoringMode mode = ScoringMode.Standardised)
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
public long GetTotalScore([NotNull] ScoreInfo score, ScoringMode mode = ScoringMode.Standardised) => score.GetDisplayScore(mode);
|
||||
|
||||
/// <summary>
|
||||
/// 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.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Users;
|
||||
using osu.Game.Users.Drawables;
|
||||
using osu.Game.Utils;
|
||||
@ -55,6 +57,7 @@ namespace osu.Game.Screens.Play.HUD
|
||||
public BindableInt Combo { get; } = new BindableInt();
|
||||
public BindableBool HasQuit { get; } = new BindableBool();
|
||||
public Bindable<long> DisplayOrder { get; } = new Bindable<long>();
|
||||
public Func<ScoringMode, long> GetDisplayScore { get; set; }
|
||||
|
||||
public Color4? BackgroundColour { get; set; }
|
||||
|
||||
@ -100,6 +103,8 @@ namespace osu.Game.Screens.Play.HUD
|
||||
|
||||
private Container scoreComponents;
|
||||
|
||||
private IBindable<ScoringMode> scoreDisplayMode;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="GameplayLeaderboardScore"/>.
|
||||
/// </summary>
|
||||
@ -112,10 +117,12 @@ namespace osu.Game.Screens.Play.HUD
|
||||
|
||||
AutoSizeAxes = Axes.X;
|
||||
Height = PANEL_HEIGHT;
|
||||
|
||||
GetDisplayScore = _ => TotalScore.Value;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
private void load(OsuColour colours, OsuConfigManager osuConfigManager)
|
||||
{
|
||||
Container avatarContainer;
|
||||
|
||||
@ -286,7 +293,9 @@ namespace osu.Game.Screens.Play.HUD
|
||||
|
||||
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 =>
|
||||
{
|
||||
@ -303,6 +312,11 @@ namespace osu.Game.Screens.Play.HUD
|
||||
HasQuit.BindValueChanged(_ => updateState());
|
||||
}
|
||||
|
||||
private void updateScore()
|
||||
{
|
||||
scoreText.Text = GetDisplayScore(scoreDisplayMode.Value).ToString("N0");
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
@ -9,12 +9,14 @@ using osu.Framework.Bindables;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Scoring.Legacy;
|
||||
|
||||
namespace osu.Game.Screens.Play.HUD
|
||||
{
|
||||
public abstract partial class GameplayScoreCounter : ScoreCounter
|
||||
{
|
||||
private Bindable<ScoringMode> scoreDisplayMode;
|
||||
private Bindable<long> totalScoreBindable;
|
||||
|
||||
protected GameplayScoreCounter()
|
||||
: base(6)
|
||||
@ -42,7 +44,8 @@ namespace osu.Game.Screens.Play.HUD
|
||||
}
|
||||
}, true);
|
||||
|
||||
Current.BindTo(scoreProcessor.TotalScore);
|
||||
totalScoreBindable = scoreProcessor.TotalScore.GetBoundCopy();
|
||||
totalScoreBindable.BindValueChanged(_ => Current.Value = scoreProcessor.GetDisplayScore(scoreDisplayMode.Value), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,9 @@
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
|
||||
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.
|
||||
/// </summary>
|
||||
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.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
@ -10,6 +9,7 @@ using osu.Game.Configuration;
|
||||
using osu.Game.Online.API.Requests;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Scoring.Legacy;
|
||||
using osu.Game.Screens.Select;
|
||||
using osu.Game.Users;
|
||||
|
||||
@ -27,15 +27,9 @@ namespace osu.Game.Screens.Play.HUD
|
||||
|
||||
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]
|
||||
private ScoreProcessor scoreProcessor { get; set; } = null!;
|
||||
|
||||
[Resolved]
|
||||
private ScoreManager scoreManager { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Whether the leaderboard should be visible regardless of the configuration value.
|
||||
/// This is true by default, but can be changed.
|
||||
@ -70,7 +64,6 @@ namespace osu.Game.Screens.Play.HUD
|
||||
private void showScores()
|
||||
{
|
||||
Clear();
|
||||
scoreBindables.Clear();
|
||||
|
||||
if (!Scores.Any())
|
||||
return;
|
||||
@ -79,12 +72,8 @@ namespace osu.Game.Screens.Play.HUD
|
||||
{
|
||||
var score = Add(s.User, false);
|
||||
|
||||
var bindableTotal = scoreManager.GetBindableTotalScore(s);
|
||||
|
||||
// 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.GetDisplayScore = s.GetDisplayScore;
|
||||
score.TotalScore.Value = s.TotalScore;
|
||||
score.Accuracy.Value = s.Accuracy;
|
||||
score.Combo.Value = s.MaxCombo;
|
||||
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);
|
||||
|
||||
local.GetDisplayScore = scoreProcessor.GetDisplayScore;
|
||||
local.TotalScore.BindTarget = scoreProcessor.TotalScore;
|
||||
local.Accuracy.BindTarget = scoreProcessor.Accuracy;
|
||||
local.Combo.BindTarget = scoreProcessor.HighestCombo;
|
||||
|
@ -237,9 +237,6 @@ namespace osu.Game.Screens.Play
|
||||
|
||||
dependencies.CacheAs(HealthProcessor);
|
||||
|
||||
if (!ScoreProcessor.Mode.Disabled)
|
||||
config.BindWith(OsuSetting.ScoreDisplayMode, ScoreProcessor.Mode);
|
||||
|
||||
InternalChild = GameplayClockContainer = CreateGameplayClockContainer(Beatmap.Value, DrawableRuleset.GameplayStartTime);
|
||||
|
||||
AddInternal(screenSuspension = new ScreenSuspensionHandler(GameplayClockContainer));
|
||||
|
Loading…
Reference in New Issue
Block a user